在Python 3中双重解压缩可迭代项会删除可迭代项吗?

时间:2018-08-24 18:00:11

标签: python

lst = iter([1, 2, 3])
print([*lst])  # >>> [1, 2, 3]
print([*lst])  # >>> []

这是打开包装的预期行为吗?我以为原始数据在拆包时不会被修改,而只是制作一个副本?

编辑:

如果是这样,其背后的原因是什么?

3 个答案:

答案 0 :(得分:2)

是的,这是打开迭代器的包装的预期行为:

>>> lst = [1, 2, 3]
>>> iter(lst)
<list_iterator at 0x7fffe8b84ef0>

迭代器只能被迭代一次,然后耗尽。

>>> i = iter(lst)
>>> next(i)
1
>>> next(i)
2
>>> next(i)
3
>>> next(i)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-11-a883b34d6d8a> in <module>()
----> 1 next(i)

StopIteration: 

迭代器协议规定,用尽的迭代器必须在其StopIteration方法的后续调用中继续引发__next__异常。因此,再次迭代是有效的(不是错误),但是迭代器不应产生任何新项:

>>> list(i)
[]

没有什么可以阻止您定义一个违反该规则的迭代器,但是such iterators are deemed "broken"

列表可迭代可以解压缩多次。

>>> lst = [1, 2, 3]
>>> print(*lst)
1 2 3
>>> print(*lst)
1 2 3

您可以根据需要在同一源列表中创建尽可能多的独立迭代器:

>>> i1 = iter(lst)
>>> i2 = iter(lst)
>>> next(i2)
1
>>> next(i2)
2
>>> next(i1)  # note: it's another 1
1

答案 1 :(得分:2)

摘自glossary entry for iterators(我的重点):

  

每次将容器对象(例如列表)传递给iter()函数或在for循环中使用它时,都会产生一个新的新迭代器。 使用迭代器尝试执行此操作只会返回上一次迭代过程中使用的相同的耗尽迭代器对象,使其看起来像一个空容器。

答案 2 :(得分:1)

您正在混淆“迭代器”和“可迭代”的术语。

(通常)不能再次迭代迭代器。另一方面,可迭代(如列表)可以:

lst = [1, 2, 3]
print([*lst])  # >>> [1, 2, 3]
print([*lst])  # >>> [1, 2, 3]