【发布时间】:2016-04-29 16:24:47
【问题描述】:
我正在编写一个 python 类,它可以在给定整数 size 和可能的 combinations 的生成器的情况下找到所有可能的 magic squares。这些组合是长度为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迭代器的项目来说,这是一个假设性问题。上面建议的两种解决方案的实现都是微不足道的,我想知道复制itertools.xxx对象是否绝对不可能。
标签: python generator itertools