我想创建一个在飞行中返回数组的生成器。例如:
import numpy as np
def my_gen():
c = np.ones(5)
j = 0
t = 10
while j < t:
c[0] = j
yield c
j += 1
使用简单的for循环:
for g in my_gen():
print (g)
我得到了我想要的东西。但是使用list(my_gen())
,我得到的列表总是包含相同的内容。
我挖得更深一些,我发现当yield c.tolist()
代替yield c
时,一切都顺利......
我无法解释自己为何会出现这种奇怪的行为......
答案 0 :(得分:6)
这是因为c
总是指向同一个numpy数组引用,你只是在生成器函数中更改c
内的元素。
简单打印时,它会在特定时刻打印完整的c
数组,因此您可以正确获取打印的值。
但是当你使用list(my_gen())
时,你继续在列表中添加c
numpy数组的相同引用,因此对该numpy数组的任何更改也会反映在列表中先前添加的元素中
当你执行yield c.tolist()
时它适用于你,因为它会从numpy数组创建一个新列表,因此你不断向list
添加新的列表对象,因此将来会更改为{{ 1}}没有反映在之前添加的列表中。
答案 1 :(得分:3)
替代生成器返回列表的副本。我保留np.ones()
作为创建数字的便捷方式,但是立即将其转换为列表(只需一次)(array.tolist()
相对昂贵)。
我产生c[:]
以避免当前版本&#39;问题
def gen_c():
c = np.ones(5,dtype=int).tolist()
j = 0
t = 10
while j < t:
c[0] = j
yield c[:]
j += 1
In [54]: list(gen_c())
Out[54]:
[[0, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[2, 1, 1, 1, 1],
[3, 1, 1, 1, 1],
[4, 1, 1, 1, 1],
[5, 1, 1, 1, 1],
[6, 1, 1, 1, 1],
[7, 1, 1, 1, 1],
[8, 1, 1, 1, 1],
[9, 1, 1, 1, 1]]
In [55]: np.array(list(gen_c()))
Out[55]:
array([[0, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[2, 1, 1, 1, 1],
[3, 1, 1, 1, 1],
[4, 1, 1, 1, 1],
[5, 1, 1, 1, 1],
[6, 1, 1, 1, 1],
[7, 1, 1, 1, 1],
[8, 1, 1, 1, 1],
[9, 1, 1, 1, 1]])
答案 2 :(得分:0)
好吧,我想因为在这个生成器中,因为我返回相同的引用,所以生成器的产量总是相同的。如果我yield np.array(c)
,那就行了......