Python:如何将生成器传递给函数?

时间:2014-07-31 16:10:04

标签: python numpy generator

简要说明

你可以通过查看这个(破碎的)片段来解决我想做的事情:

numpy.savez('tmp.npz',range(i) for i in range(2,100))

我宁愿没有办法解决这个问题:

numpy.save('tmp.npy',[range(i) for i in range(2,100)])

因为这意味着必须同时生成整个嵌套列表并将其保存在RAM中,而不是生成,传递每个子列表,然后从内存中清除。

正式/更长的说明

假设我有一些函数f,它接受​​任意数量的参数,所有参数都是列表:

def f(*args,**kwargs):  #all arguments are (non nested) lists.
    ...

但我不能(不想)改变函数f本身;我有一个生成许多列表的生成器:

nested=[<generator G, producing many lists>]

其中<G>可能类似于range(10) for i in range(10)

如何将这些列表提供给该功能? f([<G>])f(<G>)都不起作用。

3 个答案:

答案 0 :(得分:1)

我想你想要:

np.savez("tmp.npz", *(np.arange(i) for i in range(2, 100)))

请注意,*使用&#34;解包&#34;将数组生成器放入函数的参数中。我已经为外部范围切换到xrange,以避免构建列表,并为内部范围切换np.arange来创建数组。

>>> np.savez("tmp.npz", *(np.arange(i) for i in xrange(2, 100)))
>>> np.load("tmp.npz")['arr_60']
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
       34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
       51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61])

答案 1 :(得分:0)

如果查看numpy io source code,您会发现savez(file, *args, **kwds)只是一个调用函数_savez(file, args, kwds, compress)的包装器。 _savez()需要args而非*args,因此您可以传递一个将在保存功能中使用而不是在通话时使用的生成器。

我没有测试过,但是这样的事情应该有效:

from numpy.lib.npyio import _savez

_savez('tmp.npz', (range(i) for i in range(2,100)), {}, False)

答案 2 :(得分:-1)

()而非[]中包含理解将使其成为生成器理解。