生成器方法,深度复制和复制

时间:2011-06-18 13:53:09

标签: python generator deep-copy

我试图避免在自定义类(Graph类)中使用deepcopy

图形具有很少的属性,例如顶点,边缘等,以及几种生成器方法(带有yield的方法)。

我需要复制图表:例如H = deepcopy(G)但不使用深度复制来加速程序。

然后:

  • 如果我不使用deepcopy那么 新图H中的生成器方法 不要得到当前的状态 图G中的生成器方法。

  • 如果我不使用发电机方法和 选择使用完整列表生成器, 然后我会浪费计算时间 无所事事。

解决方案是尝试deepcopy某些特定的生成器方法,但是我得到了错误。

似乎发电机保存了对例如G的顶点和边缘,然后当深度复制到H时,H中的生成器仍然引用G的属性(这听起来合乎逻辑)。

那么,我是否应该使用deepcopy或者不使用生成器方法?

有第三种pythonic方式吗?

1 个答案:

答案 0 :(得分:2)

我很确定我明白你的目标是什么。这是一个简单的例子:

class Graph:
    def __init__(self, nodes):
        self.nodes = list(nodes)
        self.nodegen = self.iternodes()
    def iternodes(self):
        for node in self.nodes:
            yield node
    def copy(self):
        return Graph(self.nodes)

G = Graph([1, 2, 3, 4])
print G.nodegen.next()
H = G.copy()
print H.nodegen.next()
print G.nodegen.next()

现在当然会打印1 1 2。但是,您希望H.nodegen记住G.nodegen的状态,以便对H.nodegen.next()的调用打印2.一种简单的方法是使它们成为同一个对象:

class Graph:
    def __init__(self, nodes, nodegen=None):
        self.nodes = list(nodes)
        self.nodegen = self.iternodes() if nodegen is None else nodegen
    def iternodes(self):
        for node in self.nodes:
            yield node
    def copy(self):
        return Graph(self.nodes, self.nodegen)

这将打印1 2 3,因为调用H.nodegen.next()也会提前G.nodegen。如果这不是你想要的,那么保留一个内部计数器似乎很好,就像这样:

class Graph:
    def __init__(self, nodes, jnode=0):
        self.nodes = list(nodes)
        self.nodegen = self.iternodes()
        self.jnode = jnode
    def iternodes(self):
        while self.jnode < len(self.nodes):
            self.jnode += 1
            yield self.nodes[self.jnode-1]
    def copy(self):
        return Graph(self.nodes, self.jnode)

这将打印1 2 2,我怀疑这是你想要的。当然,当你改变self.nodes时,你将不得不改变你如何处理迭代器失效之类的事情,但我认为这应该是相当简单的。