Python: 如何将生成器传递给函数?
简要描述:
你可以通过看看这个(有点问题的)代码片段来猜测我想做什么:
numpy.savez('tmp.npz',range(i) for i in range(2,100))
我不太想用一些变通的方法,比如:
numpy.save('tmp.npy',[range(i) for i in range(2,100)])
因为这样的话,整个嵌套列表必须同时生成并保存在内存中,而不是每个子列表生成后就传递,然后再从内存中清除。
正式/详细描述:
假设我有一个函数 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 个回答
-1
用()
把一个理解式包起来,而不是用[]
,这样就会变成一个生成器理解式。
0
如果你查看一下numpy的输入输出源代码,你会发现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)
1
我觉得你想要的是:
np.savez("tmp.npz", *(np.arange(i) for i in range(2, 100)))
注意这里使用了 *
来把数组生成器的内容“展开”成函数的参数。我把外层的范围改成了 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])