【问题标题】:How does iter() work, it's giving "TypeError: iter(v, w): v must be callable"iter() 是如何工作的,它给出“TypeError: iter(v, w): v must be callable”
【发布时间】:2013-11-08 08:05:48
【问题描述】:

这段代码有什么问题?

l = [1,2,3,4,5,6]
for val in iter(l, 4):
    print (val)

返回

TypeError: iter(v, w): v must be callable

为什么 callable(list) 返回 Truecallable(l) 不返回?

编辑 这里应该首选什么方法:

  1. 手动中断
  2. 其他数百人

【问题讨论】:

    标签: python python-3.x iterator typeerror


    【解决方案1】:

    来自iter帮助:

    iter(...)
    迭代器(集合)-> 迭代器
    iter(callable, sentinel) -> 迭代器

    Get an iterator from an object.  In the first form, the argument must
    supply its own iterator, or be a sequence.
    In the second form, the callable is called until it returns the sentinel.
    

    您正在混合iter 函数的两种变体。第一个接受集合,第二个接受两个参数 - 函数和标记值。您试图传递集合标记值,这是错误的。

    简短说明:您可以从 python 的内置 help 函数中获得很多有趣的信息。只需在 python 的控制台中输入 help(iter) 即可获得相关文档。

    为什么 callabe(list) 返回 true 而 callable(l) 不返回?

    因为list 是返回新列表对象的函数。函数是可调用的(这就是函数的作用——它被调用),而这个函数返回的实例——新的列表对象——不是。

    【讨论】:

    • 很好,但我仍然坚持 callable(list)callable(list_instance) 为什么它们不同?
    • 其实list不是一个函数,而是一个类型。每个函数都是可调用的,但不是每个可调用的都是函数。
    • @thg435 list 必须实现 __init__ 方法,以便它可以初始化新的列表对象。但是这种类型如何变得可调用 - 通过实现__call__ 方法?或__init__ 的实现使其可调用?
    • @aga: 不,type 类型实现了__call__,这就是为什么所有类型(=classes)都是可调用的。不是他们的实例。
    • @thg435 感谢您的解释,似乎我对python中的类型和类一团糟。 :) 今天晚上我会读到它。
    【解决方案2】:

    当使用两个参数调用时,iter 接受一个可调用值和一个标记值。它的行为就像是这样实现的:

    def iter2args(f, sentinel):
        value = f()
        while value != sentinel:
            yield value
            value = f()
    

    作为f 传入的内容必须是可调用的,这意味着您可以像调用函数一样调用它。内置的 list 是一个 type 对象,您可以通过像函数一样调用它来创建新的列表实例:

    >>> list('abcde')
    ['a', 'b', 'c', 'd', 'e']
    

    你传入的列表l是一个已有的列表实例,不能像函数一样使用:

    >>> l = [1,2,3,4,5,6]
    >>> l(3)
    Traceback (most recent call last):
      File "<pyshell#20>", line 1, in <module>
        l(3)
    TypeError: 'list' object is not callable
    

    因此,list 类型对象和列表实例之间存在巨大而重要的区别,当与 iter 一起使用时会显示出来。

    要遍历列表直到到达哨兵,您可以使用itertools.takewhile

    import itertools
    for val in itertools.takewhile(l, lambda x: x!= 4):
        print(val) 
    

    【讨论】:

    • 最后一个例子导致python 3的错误“'function' object is not iterable”...
    【解决方案3】:

    它与被传递的第二个值(所谓的哨兵值)有关,这确保了被迭代的对象是可调用的,即。一个函数。 因此,对于 iter() 的每次迭代,它都会在传递的对象上调用 __next__()

    iter() 有两种不同的行为,

    • 没有标记值
    • 带有标记值

    文档中的示例非常适合理解它

    with open("mydata.txt") as fp:
        for line in iter(fp.readline, "STOP"): #fp.readline is a function here.
            process_line(line)
    

    【讨论】:

      【解决方案4】:

      查看文档:http://docs.python.org/2/library/functions.html#iter

      iter 中的第二个参数存在时,第一个参数的处理方式将大不相同。它应该是在每个步骤中调用的函数。如果它返回哨兵(即第二个参数),则迭代停止。例如:

      l=[1,2,3,4,5,6]
      
      index = -1
      def fn():
          global index
          index += 1
          return l[index]
      
      for val in iter(fn, 4):
          print (val)
      

      编辑:如果您只想遍历列表并在看到哨兵时停止,那么我建议您这样做:

      for val in l:
          # main body
          if val == 4:
              break
      

      【讨论】:

      • 那么使用哨兵值对该列表进行迭代的最佳方法是什么?
      • @new-kid 如果您想使用iter(callable, sentinel) 来执行此操作,只需使用iter(the_list.__next__, 4)。 [在python2中将__next__替换为next]
      • @new-kid 我觉得iter(the_list.__next__,4) 很丑,而且不像休息时间那样容易阅读。此外,不应直接使用“私有”方法(即以__ 开头的方法)。但这是一个选择问题。
      • @new-kid 我同意怪诞的说法:只需使用break。顺便说一句,我刚刚意识到我的建议不是 100% 正确,因为 lists 确实没有__next__。你必须这样做:iter(iter(the_list).__next__, 4) 这真的很丑。
      • @freakish 我会期望它会更慢。请注意,在执行 for element in iter(callable, sentinel) 时,解释器必须为每次迭代执行 generic 调用 (PyObject_Call),而使用 for element in iterable 时,解释器可以安全地调用迭代器上的 PyObject_Next,而无需通用调用的开销。但是请注意,使用iter(callable, sentinel) 比使用while True + 调用函数和显式break(我经常看到使用)的等效解决方案更快
      【解决方案5】:

      请记住,类是 Python 中的对象。

      >>> callable(list)
      True
      

      意味着 list 本身 是可调用的,而不是它的实例是可调用的。如您所见,它们不是:

      >>> callable([])
      False
      

      事实上,Python 中的所有类都是可调用的——如果它们没有像 list 这样的字面量,这是实例化它们的常用方法。考虑:

      def MyClass:
           pass
      
      a = MyClass()
      

      最后一行调用MyClass 类对象,它创建了一个实例——因此,MyClass 必须是可调用的。但是你不会期望 instance 是可调用的,因为MyClass 本身并没有定义__call__

      另一方面,MyClass 的类(即它的元类type确实

      >>> type.__call__
      <slot wrapper '__call__' of 'type' objects>
      

      这就是 MyClass 可调用的原因。

      【讨论】:

        【解决方案6】:

        为什么 callabe(list) 返回 true 而 callable(l) 不返回?

        因为list 是Python 内置函数,而l 是列表。

        【讨论】:

        • 那么 l 不是 list 类的实例吗?
        • @new-kid 您的评论毫无意义。 list 是一个类,all 类都是可调用的(你调用它们来创建实例)。实例不必是可调用的。想一想:[1,2,3]() 应该怎么做?或1()int 类是可调用的,但 int 实例不是。
        【解决方案7】:

        也许您正在寻找类似的东西?

        >>> l = [1,2,3,4,5,6]
        >>> l_it = iter(l)
        >>> while True:
        ...     next_val = next(l_it, None)
        ...     if not next_val:
        ...             break
        ...     print(next_val)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-05-12
          • 1970-01-01
          • 2016-02-16
          • 2011-11-08
          • 2021-04-03
          • 2020-12-03
          • 2012-06-14
          • 2017-04-08
          相关资源
          最近更新 更多