Python生成器与numpy数组

时间:2015-10-07 09:51:44

标签: python numpy generator

我想创建一个在飞行中返回数组的生成器。例如:

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时,一切都顺利......

我无法解释自己为何会出现这种奇怪的行为......

3 个答案:

答案 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),那就行了......