iter() 是如何工作的,它给出“TypeError: iter(v, w): v 必须可调用”

问题描述 投票:0回答:8

这段代码有什么问题?

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
8个回答
8
投票

来自

iter
帮助:

iter(...)
iter(集合) -> 迭代器
iter(可调用,哨兵) -> 迭代器

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) 不返回 true?

因为

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


5
投票

当使用两个参数调用时,

iter
采用可调用值和哨兵值。它的行为就像是这样实现的:

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

作为

f
传入的内容必须是 callable,这意味着您可以像函数一样调用它。内置的
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) 

4
投票

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

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)

3
投票

查看文档: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

3
投票

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

>>> callable(list)
True

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

>>> callable([])
False

事实上,Python 中的所有类都是可调用的 - 如果它们没有像

list
这样的文字,这是实例化它们的常用方法。考虑:

def MyClass:
     pass

a = MyClass()

最后一行调用

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

另一方面,类of

MyClass
(即它的元类,
type
确实

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

这就是使

MyClass
可调用的原因。


0
投票

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

因为

list
是 Python 内置函数,而
l
是一个列表。


0
投票

原因已在之前的回答中解释过。

这是修改后的代码,可以在Python中执行。

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

-1
投票

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

>>> 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)
© www.soinside.com 2019 - 2024. All rights reserved.