Python中迭代器和可重用性的混淆
我目前正在阅读Python 3.5的官方文档 它声明Python中迭代器和可重用性的混淆,python,python-3.x,iterator,documentation,iterable,Python,Python 3.x,Iterator,Documentation,Iterable,我目前正在阅读Python 3.5的官方文档 它声明range()是iterable,而list()和for是迭代器 >>> next(zipped) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration 但是,它声明zip()生成迭代器 我的问题是,当我们使用此说明时: list(zip(list1, list2
range()
是iterable,而list()
和for
是迭代器
>>> next(zipped)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
但是,它声明zip()
生成迭代器
我的问题是,当我们使用此说明时:
list(zip(list1, list2))
list(zip(list1, list2))
我们是否使用一个迭代器(
list()
)来迭代另一个迭代器?由于重复使用术语“迭代器”,文档在这里造成了一些混乱
有三个组件可供选择:
for
循环就是后者的一个例子,因此#3。for
循环使用生成一个迭代器(#2以上)用于循环要循环的任何内容,因此“whatever”必须是iterable(#1以上)
range()
是#1;这是一个不可分割的对象。您可以独立地对其进行多次迭代:
>>> r = range(5)
>>> r_iter_1 = iter(r)
>>> next(r_iter_1)
0
>>> next(r_iter_1)
1
>>> r_iter_2 = iter(r)
>>> next(r_iter_2)
0
>>> next(r_iter_1)
2
这里的r\u iter\u 1
和r\u iter\u 2
是两个独立的迭代器,每次您请求下一个项目时,他们都会根据自己的内部簿记进行
list()
是iterable(#1)和迭代消费者(#3)的示例。如果将另一个iterable(#1)传递给list()
调用,将生成一个包含该iterable中所有元素的列表对象。但是列表对象本身也是不可编辑的
Python3中的zip()
,接受多个iterables(#1),本身就是一个迭代器(#2)zip()
为您提供的每个iterable存储一个新的迭代器(#2)。每次询问zip()
下一个元素时,zip()
都会从包含的每个ITerable中使用下一个元素构建一个新元组:
>>> lst1, lst2 = ['foo', 'bar'], [42, 81]
>>> zipit = zip(lst1, lst2)
>>> next(zipit)
('foo', 42)
>>> next(zipit)
('bar', 81)
因此,最后,
list(zip(list1,list2))
使用list1
和list2
作为iterables(#1),zip()
在外部list()
调用使用这些(#3)时使用它们 文件措词不当。以下是您所指的部分:
我们说这样的对象是可移植的,也就是说,适合作为函数和结构的目标,这些函数和结构期望从中获得连续的项目,直到供应耗尽为止。我们已经看到,该语句就是这样一个迭代器。功能是另一个;它从iterables创建列表:
>>> lst1, lst2 = ['foo', 'bar'], [42, 81]
>>> zipit = zip(lst1, lst2)
>>> next(zipit)
('foo', 42)
>>> next(zipit)
('bar', 81)
在本段中,迭代器并不是指Python迭代器对象,而是指“在某个对象上进行迭代的某个对象”的一般概念。特别是,for
语句不能是迭代器对象,因为它根本不是对象;这是一种语言结构
要回答您的具体问题:
。。。当我们使用本说明时:
list(zip(list1, list2))
list(zip(list1, list2))
我们是否使用迭代器(list()
)来迭代另一个迭代器
不,不是迭代器。它是列表
类型的构造函数。它可以接受任何iterable(包括迭代器)作为参数,并使用该iterable构造列表
是一个迭代器函数,即返回迭代器的函数。在您的示例中,它返回的迭代器被传递到list()
,这将从中构造一个list
对象
判断对象是否是迭代器的一种简单方法是使用它进行调用,并查看发生了什么:
>>> list1 = [1, 2, 3]
>>> list2 = [4, 5, 6]
请注意,在list3
中只找到迭代器的最后两个元素,因为我们已经使用next()
使用了第一个元素
>>下一步(列表3)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:“list”对象不是迭代器
这不起作用,因为列表不是迭代器
>>> next(zipped)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>下一步(压缩)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
停止迭代
这一次,虽然
zip
是一个迭代器,但调用next()
会引发StopIteration
,因为构建list3
for
不是迭代器range()
是一个序列,就像list
一样,两者都是可编辑的。为iterable创建一个新的迭代器来执行实际的迭代。迭代器这个词实际上有两种不同的含义。我建议不要对单词的确切含义大惊小怪。list()
和for
都要求iterable提供迭代器。迭代器是它们自己的迭代器zip()
是一个迭代器,而不是一个iterable,因为它不能生成新的迭代器(只能迭代一次)。@MartijnPieters好吧,Python官方教程页面确实说“for语句就是这样一个迭代器。函数list()是另一个”。我猜他们的意思是这是一个迭代的东西(在给定的东西上)。我认为这里的混淆是消费者(驱动迭代)和生产者(可以用作)。该死的,你是怎么做到的?;-)@零:乘飞机到另一个国家旅行;我跳进了连接的短脉冲;-)从您的回答和@ZeroPiraeus的回答中,我可以看到文档中有时使用术语迭代器
来指代迭代器
,有时指代迭代器的使用者。但是为什么范围()
被认为是迭代器,而不是iterable
?它的工作原理与zip()
的工作原理不一样吗?不,是的