如何从生成器中生成一个对象并立即将其忘记,以便它不占用内存?
例如,在以下函数中:
def grouper(iterable, chunksize):
"""
Return elements from the iterable in `chunksize`-ed lists. The last returned
element may be smaller (if length of collection is not divisible by `chunksize`).
>>> print list(grouper(xrange(10), 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
"""
i = iter(iterable)
while True:
chunk = list(itertools.islice(i, int(chunksize)))
if not chunk:
break
yield chunk
我不希望函数在生成后保留对
chunk
的引用,因为它不会被进一步使用,而且只会消耗内存,即使所有外部引用都已消失。编辑:使用python.org中的标准python 2.5/2.6/2.7。
解决方案(几乎同时由@phihag和@owen提出):将结果包装在一个(小)可变对象中并匿名返回块,只留下小容器:
def chunker(iterable, chunksize):
"""
Return elements from the iterable in `chunksize`-ed lists. The last returned
chunk may be smaller (if length of collection is not divisible by `chunksize`).
>>> print list(chunker(xrange(10), 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
"""
i = iter(iterable)
while True:
wrapped_chunk = [list(itertools.islice(i, int(chunksize)))]
if not wrapped_chunk[0]:
break
yield wrapped_chunk.pop()
通过这种内存优化,您现在可以执行如下操作:
for big_chunk in chunker(some_generator, chunksize=10000):
... process big_chunk
del big_chunk # big_chunk ready to be garbage-collected :-)
... do more stuff
最佳答案
如果您真的想获得这个功能,我想您可以使用包装器:
class Wrap:
def __init__(self, val):
self.val = val
def unlink(self):
val = self.val
self.val = None
return val
可以像
def grouper(iterable, chunksize):
i = iter(iterable)
while True:
chunk = Wrap(list(itertools.islice(i, int(chunksize))))
if not chunk.val:
break
yield chunk.unlink()
这基本上与phihag对
pop()
;所做的相同)