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]])