Как я могу получить объект из генератора и немедленно его забыть, чтобы он не занимал память?
Например, в следующей функции:
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
после ее уступки, поскольку она больше не используется и просто потребляет память, даже если все внешние ссылки удалены.
EDIT: используя стандартный Python 2.5/2.6/2.7 на python.org.
Решение (предлагаемое почти одновременно @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