【问题标题】:Python appending to and yielding a listPython追加并产生一个列表
【发布时间】:2015-12-07 12:05:24
【问题描述】:

这里发生了什么?为什么list(f(seq)) 返回的不是f 产生的元素列表?

>>> def f(seq):
...   a = []
...   for i in seq:
...     yield a
...     a.append(i)
...
>>> f([1,2,3])
<generator object f at 0x1066c7aa0>
>>> b = f([1,2,3])
>>> b.next()
[]
>>> b.next()
[1]
>>> b.next()
[1, 2]
>>> b.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> list(f([1,2,3]))
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]

【问题讨论】:

  • 消除这种依赖关系的一个解决方案是在生成时浅复制列表,将yield a 替换为yield a[:]。这是很多复制,但如果你想返回独立的列表,这是必要的。

标签: python generator


【解决方案1】:

您已经在函数中生成了对列表a 的完整引用。当list(f([1,2,3]))被调用时,结果就是[a, a, a],而a的最终形式是[1, 2, 3]

如果您保存了 f.next() 调用的所有结果,这也没有什么不同。

>>> v1 = b.next()
>>> v2 = b.next()
>>> v1
[1]
>>> v2
[1]
>>> v3 = b.next()
>>> v4 = b.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> v1
[1, 2, 3]

同样,这是正确的,因为 a 已生成,并且是对函数 f 内相同内部列表的相同引用。

【讨论】:

  • @achampion 不得不回滚你的编辑,因为你实际上并没有在你的 Python shell 中运行他的代码来查看输出是否完全一样。
  • 确认,道歉。
【解决方案2】:

您正在生成您在生成器中创建的列表,而不是列表的副本。列表是可变的,因此对该列表的任何更改都会反映在对该列表的所有引用中
考虑一下:

>>> a = [[]]*4      # Create a list of 4 references to the same list
>>> a[0].append(1)  # Add 1 the first reference
>>> a
[[1], [1], [1], [1]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 2017-02-06
    • 2016-07-03
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多