python - 在不破坏内存的情况下复制生成器

标签 python generator python-itertools

我正在编写一个 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/

相关文章:

python - 如何在 python 中创建文件存在的 if 循环?

python - python中寻址属性的风格

python - 如何检查 screen 是否正在运行?

javascript - 在 v8 中实现无限列表

python - 是否可以在 Python 中将 RabbitMQ 直接回复功能与 Pika 生成器使用者一起使用?

python - 展平嵌套的生成器表达式

python - 向导的替代品

linux - 为什么 Unix Makefiles 的 CMake 生成器会删除文件?

python - 如何从 python 中的同一列表中获取不同长度的多种组合?

python - 为什么文档提到 padnone 模拟内置 map 的行为?