PyP*_*rog 1 python iterator list
我有一个__len__定义了方法的迭代器.问题:
如果调用list(y)并且y __len__定义了一个方法,则__len__调用它.
1)为什么?
在我的输出中,您将在第一次尝试时看到len(list(y))为0.如果查看列表输出,您将看到在第一次调用时,我收到一个空列表,在第二次调用时,我收到"正确"列表.
2)为什么它会返回一个长度为零的列表?
3)为什么列表长度在所有后续呼叫中都是正确的?
另请注意,调用"枚举"不是问题.C类做同样的事情,但使用while循环并调用next().
码:
showcalls = False
class A(object):
_length = None
def __iter__(self):
if showcalls:
print "iter"
self.i = 0
return self
def next(self):
if showcalls:
print "next"
i = self.i + 1
self.i = i
if i > 2:
raise StopIteration
else:
return i
class B(A):
def __len__(self):
if showcalls:
print "len"
if self._length is None:
for i,x in enumerate(self):
pass
self._length = i
return i
else:
return self._length
class C(A):
def __len__(self):
if showcalls:
print "len"
if self._length is None:
i = 0
while True:
try:
self.next()
except StopIteration:
self._length = i
return i
else:
i += 1
else:
return self._length
if __name__ == '__main__':
a = A()
print len(list(a)), len(list(a)), len(list(a))
print
b = B()
print len(list(b)), len(list(b)), len(list(b))
print
c = C()
print len(list(c)), len(list(c)), len(list(c))
Run Code Online (Sandbox Code Playgroud)
输出:
2 2 2
0 2 2
0 2 2
Run Code Online (Sandbox Code Playgroud)
如果调用list(y)并且y 定义了 len方法,则调用len.为什么?
因为构建具有最终长度的结果列表(如果从一开始就知道)比以空列表开始并且一次附加一个项目更快.并且__len__必须100%保证可靠.
IOW,也没有实施特别的方法,如__len__如果当你不能返回一个可靠值.
至于第二个问题,你的实现__len__被破坏了,因为它们使用了迭代器(并且没有将它返回到它的原始状态) - 所以它们没有为后续.next调用留下任何项,所以list构造函数得到一个StopIteration并确定你__len__只是片状(不幸的是,比穷人更list难以猜测......! - ).