Python 带有 numpy 数组的生成器
Python generator with numpy array
我想创建一个 returns 动态数组的生成器。例如:
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
时,一切正常...
我无法解释为什么会出现这种奇怪的行为...
那是因为 c
总是指向同一个 numpy 数组引用,你只是在生成器函数中改变 c
里面的元素。
当简单打印时,它会在特定时刻打印完整的 c
数组,因此您可以正确打印值。
但是当您使用 list(my_gen())
时,您会不断将对 c
numpy 数组的相同引用添加到列表中,因此对该 numpy 数组的任何更改也会反映在先前添加的元素中列表。
它在您执行 yield c.tolist()
时对您有用,因为这会从 numpy 数组创建一个新列表,因此您不断向 list
添加新的列表对象,因此将来会更改为c
未反映在之前添加的列表中。
好的,我想是因为在这个生成器中,因为我返回相同的引用,所以生成器总是产生相同的结果。如果我 yield np.array(c)
,那就行了...
替代生成器returns列表的副本。我保留 np.ones()
作为创建数字的便捷方式,但立即将其转换为列表(仅一次)(array.tolist()
相对昂贵)。
我放弃 c[:]
以避免 'current version' 问题。
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]])
我想创建一个 returns 动态数组的生成器。例如:
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
时,一切正常...
我无法解释为什么会出现这种奇怪的行为...
那是因为 c
总是指向同一个 numpy 数组引用,你只是在生成器函数中改变 c
里面的元素。
当简单打印时,它会在特定时刻打印完整的 c
数组,因此您可以正确打印值。
但是当您使用 list(my_gen())
时,您会不断将对 c
numpy 数组的相同引用添加到列表中,因此对该 numpy 数组的任何更改也会反映在先前添加的元素中列表。
它在您执行 yield c.tolist()
时对您有用,因为这会从 numpy 数组创建一个新列表,因此您不断向 list
添加新的列表对象,因此将来会更改为c
未反映在之前添加的列表中。
好的,我想是因为在这个生成器中,因为我返回相同的引用,所以生成器总是产生相同的结果。如果我 yield np.array(c)
,那就行了...
替代生成器returns列表的副本。我保留 np.ones()
作为创建数字的便捷方式,但立即将其转换为列表(仅一次)(array.tolist()
相对昂贵)。
我放弃 c[:]
以避免 'current version' 问题。
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]])