【问题标题】:TypeError: object of type 'enumerate' has no len()TypeError:“枚举”类型的对象没有 len()
【发布时间】:2020-02-11 04:38:59
【问题描述】:

这是我的代码:

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()

我认为我们可以将枚举对象视为列表。我在网上找到了将枚举对象视为列表的解决方案。谁能解释一下我为什么会收到这个错误?

【问题讨论】:

  • 将它们视为列表并不一定意味着它们具有len 属性。从技术上讲,您可以转换为列表,然后相应地设置子集。此外,您可以在将 a 转换为枚举类之前设置 f,l = 0,len(a)-1
  • enumerate 对象与lists 不同,它们是可迭代的。 Iterables 不必支持len,因为它们可以是无穷无尽的。

标签: python enumerate


【解决方案1】:

enumerate 只是向可迭代对象添加一个计数器,它不是可迭代对象。 enumerate对象可以转成list,然后就可以使用了。

至于你的问题,非枚举解决方案可以是

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]

【讨论】:

    【解决方案2】:
    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__']
    

    与支持len()list不同:

    >>> 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。这就是为什么你在your answer 中说“它甚至不能下标”。

    我认为我们可以将枚举对象视为列表。

    不,不是真的。 枚举对象的行为更像iterator,这是 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 循环的工作方式和结束方式与您使用 枚举对象next() 方法时相同。

    enumerate() 文档中所示,如果您需要类似列表的内容,您只需将其转换为list

    >>> a = list(enumerate([1,2,3]))
    >>> a
    [(0, 1), (1, 2), (2, 3)]
    

    【讨论】:

      【解决方案3】:

      此解决方案有效。我必须先将枚举对象转换为列表。否则它甚至不能下标。

      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
      

      【讨论】:

      • @cricket_007 a 是一个列表。它在问题中。或者你的意思是它代表什么?
      • 由于格式问题,不在原帖中,我的错
      • @cricket_007 哦,参数。对,我刚刚修好了。
      猜你喜欢
      • 1970-01-01
      • 2015-08-21
      • 2019-05-23
      • 2013-04-18
      • 2015-01-21
      • 2021-12-19
      • 2018-08-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多