TypeError: объект типа 'enumerate' не имеет len () - PullRequest
1 голос
/ 11 февраля 2020

Вот мой код:

def twosum(a, t):
    a = enumerate(a)
    f, l = 0, len(a)-1
    while(f <= l):
        if (a[f][1] + a[l][1] == t):
            return [a[f][0], a[l][0]]
        else:
            f += 1
            l -= 1
    return

print(twosum([2, 7, 11, 15], 9)) 

Я получаю ошибку:

TypeError: object of type 'enumerate' has no len()

Я думал, что мы можем рассматривать перечисляемые объекты как списки. Я нашел решения онлайн, которые обрабатывают перечисляемые объекты как списки. Кто-нибудь может объяснить, почему я получаю эту ошибку?

Ответы [ 3 ]

1 голос
/ 11 февраля 2020

enumerate просто добавляет счетчик к итерируемой, это не итерируемой. перечислите объекты, которые можно преобразовать в список и затем использовать.

Что касается вашей проблемы, решение без перечисления может быть

def twosum(a, t):
    f, l = 0, len(a) - 1
    while f <= l:
        if a[f] + a[l] == t:
            return [a.index(a[f]), a.index(a[l])]
        else:
            f += 1
            l -= 1
twosum([2, 7, 11, 15], 17)

Это возвращает [0, 3]. Для перечислимого решения

def twosum(a, t):
    f, l = 0, len(a)-1
    a = list(enumerate(a))
    while(f <= l):
        if (a[f][1] + a[l][1] == t):
            return [a[f][0], a[l][0]]
        else:
            f += 1
            l -= 1
twosum([2, 7, 11, 15], 17)

Это также возвращает [0, 3]

1 голос
/ 11 февраля 2020
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)]
0 голосов
/ 11 февраля 2020

Это решение сработало. Сначала мне пришлось преобразовать объект перечисления в список. В противном случае это даже не было подпиской.

def twosum(a, t):
    a = enumerate(a)
    a = sorted(a, key=lambda x:x[1])
    f, l = 0, len(a)-1
    while(f < l):
        if (a[f][1] + a[l][1] == t):
            return [a[f][0], a[l][0]]
        elif (a[f][1] + a[l][1] < t):
            f += 1
        else:
            l -= 1
...