我正在编写一个 python 类来查找所有可能的 magic squares给定一个整数 size
和一个可能的 combinations
的生成器。这些组合是长度为 size**2
的元组,并被拆分为 size
×size
网格。代码本身工作正常,但重用生成器似乎需要 itertools.tee
。在下面显示的示例中,这会导致线程使用的内存跳到 300MB,因为迭代器中的每个值都存储在列表中。
from itertools import permutations, tee
class MagicSquare:
def __init__(self, size, combinations):
self.size = size
self.range = range(self.size)
self.combinations = combinations
def getGrid(self, entries):
return [ entries[self.size*i:self.size*(i+1)] for i in self.range ]
def checkGrid(self, grid):
check_sum = sum(grid[0])
if any( sum(row) != check_sum for row in grid ):
return False
if any( sum(row[col] for row in grid) != check_sum for col in self.range ):
return False
if sum(grid[diag][diag] for diag in self.range) != check_sum:
return False
if sum(grid[diag][self.size-diag-1] for diag in self.range) != check_sum:
return False
return True
def solutions(self):
combinations, self.combinations = tee(self.combinations)
for entries in combinations:
grid = self.getGrid(entries)
if self.checkGrid(grid):
yield grid
if __name__ == '__main__':
combs = permutations(range(20,30), 9)
ms = MagicSquare(3, combs)
for solution in ms.solutions():
for row in solution:
print row
print
对于这个问题,我想到了两个明显的解决方案。首先,我可以请求提供生成器的函数而不是请求生成器本身,但这需要用户包装他们的生成器表达式。其次,我可以缓存解决方案。为了争论,假设如果没有足够数量的解决方案,我不想再检查对角线,所以我需要更新 checkGrid
并重复 combinations
.
所以,我的问题是:是否真的没有办法在不造成这种潜在的巨大内存问题的情况下复制生成器?我不关心保留生成器的部分状态,我只希望它迭代与原始生成器相同的值。
编辑
看来在 Python 3.X 中,您可以使用 copy.deepcopy
来复制 itertools
对象,其依赖项都是可拾取的。
最佳答案
没有什么是不可能的...
以下恰好适用于 itertools.permutations
。不要假设它适用于任何可迭代对象,因为它不会!
>>> from itertools import permutations
>>> combs = permutations(range(20,30), 9)
>>> from copy import deepcopy
>>> combs2 = deepcopy(combs)
>>> next(combs)
(20, 21, 22, 23, 24, 25, 26, 27, 28)
>>> next(combs2)
(20, 21, 22, 23, 24, 25, 26, 27, 28)
关于python - 在不破坏内存的情况下复制生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34957388/