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

2024-03-29 05:04:59 发布

您现在位置:Python中文网/ 问答频道 /正文

这个代码有什么问题?在

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

它回来了

^{pr2}$

为什么可调用(list)返回Truecallable(l)不返回?在

编辑 此处应首选哪种方法:

  1. 手动中断
  2. 其他一百个

Tags: 方法代码intrue编辑forval手动
3条回答

它与第二个值pass(一个所谓的sentinel值)有关,这确保被迭代的对象是一个可调用的,即函数。 因此,对于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)

来自iter帮助:

iter(...)
iter(collection) -> iterator
iter(callable, sentinel) -> iterator

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函数的两个变体。第一个接受集合,第二个接受两个参数-函数和sentinel值。您试图传递collectionsentinel值,这是错误的。在

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

Why does callabe(list) return true but callable(l) does not?

因为list是返回新列表对象的函数。函数是可调用的(这是函数所做的-它被调用),而这个函数返回的实例-new list object-不是。在

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

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

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

^{pr2}$

您传入的列表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一起使用时会显现出来。在

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

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

相关问题 更多 >