TypeError: object of type 'enumerate' has no len()
Функция len()
требует, чтобы объекты имели или реализовывали функцию __len__
.
object.__len__(self)
Вызывается для реализации встроенной функции len()
. Должен возвращать длину объекта, целое число> = 0.
К сожалению, enumerate
возвращает перечисляемый объект , который не имеет __len__
:
>>> a = enumerate([1,2,3])
>>> a
<enumerate object at 0x10e496be0>
>>> dir(a)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__',
'__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__']
В отличие от list
, которые поддерживают len()
:
>>> a = [1,2,3]
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',
...
'__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__',
'__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__',
...
'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
Вы также можете заметить, что перечисляющий объект также не имеет метод __getitem__
, который позволяет получить доступ к элементам, используя obj[index]
, как для list'
s. Вот почему вы сказали в своем ответе , что " это даже не подписно ".
Я думал, что мы можем рассматривать перечисляемые объекты как списки.
Нет, не совсем. Перечисляемый объект ведет себя больше как итератор , который является Python способом представления " потока данных ", который может быть бесконечным. Вы получаете доступ к данным, вызывая метод next()
до тех пор, пока не будет сгенерировано исключение (StopIteration
).
Повторные вызовы метода __next__()
итератора (или передача его во встроенную функцию next()
) возвращает последовательные элементы в потоке. Когда больше нет доступных данных, вместо этого возникает исключение StopIteration
.
>>> a = enumerate([1,2,3])
>>> next(a)
(0, 1)
>>> next(a)
(1, 2)
>>> next(a)
(2, 3)
>>> next(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Я думаю, вы понимаете, что они похожи на list
, потому что вы также можете поместить их в циклическая конструкция, подобная обычной list
, и итерации по каждому элементу:
>>> a = enumerate([1,2,3])
>>> for i in a:
... print(i)
...
(0, 1)
(1, 2)
(2, 3)
В этом случае для каждой итерации объект перечисления предоставляет кортеж, содержащий индекс следующего элемент и сам элемент. for
l oop работает и заканчивается так же, как и при использовании метода next()
объекта перечисления .
Как показано в enumerate()
документы, вы можете просто привести его в list
, если вам нужно что-то похожее на список:
>>> a = list(enumerate([1,2,3]))
>>> a
[(0, 1), (1, 2), (2, 3)]