用`with`语句命名列表元素

时间:2019-02-20 09:37:28

标签: python list sequence with-statement

我想引用列表(mem[0])中具有不同名称(mem)的元素(fetch):

mem = [0]
f = open("File.lx", "rb").read()
for b in f: mem += [b]
size = len(mem)

while mem[0] < size:        #using mem[0]
    char = (mem[0]*2)+1
    source = mem[char]
    target = mem[char + 1]

    mem[0] += 1
    mem[target] = mem[source]

然后我用with语句进行了尝试:

mem = [0]
f = open("File.lx", "rb").read()
for b in f: mem += [b]
size = len(mem)

with mem[0] as fetch:        #with statement
   while fetch < size:       #using mem[0] as fetch
    char = (fetch*2)+1
    source = mem[char]
    target = mem[char + 1]

    fetch += 1
    mem[target] = mem[source]

但是我得到一个错误:

Traceback (most recent call last):
  File "C:\documents\test.py", line 6, in <module>
    with mem[0] as fetch:
AttributeError: __enter__

我认为这就是方法,因为这是使用文件对象完成的方式:

with open("File.lx", "rb") as file:
    fileBytes = file.read()

我阅读了with语句的docs,它说__exit()____enter()__方法已加载。根据我阅读AttributeError后的理解,我猜测序列元素(mem[0])没有__enter()__方法。

2 个答案:

答案 0 :(得分:1)

正如已经提到的注释,mem[0]是一个文字整数,它没有__enter__关键字起作用所需的__exit__as如果您只使用mem[0]

的话,确实会更简单

但是那太简单了,您可以做什么(作为练习,实际上并没有做到) 扩展int类,并添加__enter____exit__,如下所示:

class FancyInt(int):
    def __enter__(self):
        return self
    def __exit__(self, *args):
        pass

mem = [FancyInt(0)]
with mem[0] as fetch:
    print(fetch)

这很简洁,但是fetch LITERAL!的别名!如果更改fetchmem[0]不会改变!

答案 1 :(得分:0)

您似乎想要一个可变的对象,该对象充当列表中特定位置的别名。我可以在其中看到 some 实用程序(因为在Python中显式索引有些难看)。您可以创建这样的类。这是一个概念证明,它在代码中实现了您尝试使用fetch完成的三件事:

class Fetcher:
    def __init__(self,target_list, index):
        self._list = target_list
        self._i = index

    def __iadd__(self,v):
        self._list[self._i] += v
        return self

    def __mul__(self,v):
        return self._list[self._i] * v

    def __lt__(self,v):
        return self._list[self._i] < v

例如,

mem = [0,1,2]
fetch = Fetcher(mem,0)

print(fetch < 2) #true
mem[0] = 1
print(fetch < 2) #still true
fetch += 1
print(fetch < 2) #false!
print(mem[0]) #2, showing that mem[0] was changed
print(fetch*2) #4 -- but 2*fetch won't work!

最后一行表明,您在这里可以达到的目标是有限的。为了使它真正有用,您将需要实现更多的魔术方法(除了__iadd__等之外)。这一切是否对避免[0]有用,您都是法官。