Python 追加并生成列表
Python appending to and yielding a list
这是怎么回事?为什么 list(f(seq))
return 不是 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]]
您已经在函数内生成了对列表 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
.
内相同内部列表的相同引用
您生成的是您在生成器中创建的列表,而不是列表的副本。列表是可变的,因此对该列表的任何更改都会反映在对该列表的所有引用中。
考虑一下:
>>> 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]]
这是怎么回事?为什么 list(f(seq))
return 不是 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]]
您已经在函数内生成了对列表 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
.
您生成的是您在生成器中创建的列表,而不是列表的副本。列表是可变的,因此对该列表的任何更改都会反映在对该列表的所有引用中。
考虑一下:
>>> 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]]