У меня есть итератор с определенным методом __len__
. Вопросы:
Если вы вызываете list (y) и у y определен метод __len__
, то вызывается __len__
.
1) Почему?
В моем выводе вы увидите, что len (list (y)) равен 0 с первой попытки. Если вы посмотрите на вывод списка, вы увидите, что при первом вызове я получаю пустой список, а при втором вызове получаю «правильный» список.
2) Почему он вообще возвращает список нулевой длины?
3) Почему длина списка корректируется при всех последующих вызовах?
Также обратите внимание, что вызов enumerate не является проблемой. Класс 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))
Выход:
2 2 2
0 2 2
0 2 2