Python中迭代器和可重用性的混淆

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

我目前正在阅读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))
list(zip(list1, list2))

我们是否使用一个迭代器(
list()
)来迭代另一个迭代器?

由于重复使用术语“迭代器”,文档在这里造成了一些混乱

有三个组件可供选择:

  • 易怒;您可以一个接一个地迭代并获取它们的元素

  • 迭代器;做迭代的事情。每次你想要一步一步地完成一个iterable的所有项目,你都需要其中一个来跟踪你在这个过程中的位置。这些是不可重复使用的;一旦你到达终点,就这样了。对于大多数iterables,您可以创建多个独立的迭代器,每个迭代器独立跟踪位置

  • 迭代器的消费者;那些想要对物品做点什么的东西

  • 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()
    的工作原理不一样吗?不,是的