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

发布于 2024-11-15 23:20:47 字数 596 浏览 3 评论 0原文

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

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

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

然后:

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

  • 如果我不使用生成器方法并且 选择使用完整列表生成器, 那么我会浪费计算时间 没有做任何有用的事情。

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

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

那么,我到底是注定要使用deepcopy还是不使用生成器方法呢?

还有第三种Python方式吗?

I am trying to avoid the use of deepcopy in a custom class (a Graph class)

The graphs have few attributes, such as vertices, edges, etc. and several generator methods (methods with yield).

I need to copy the graph: e.g. H = deepcopy(G) but not using deepcopy in order to speed up the program.

Then:

  • If I do not use deepcopy then the
    generator methods in the new graph H
    do not get the current state of the
    generator methods in graph G.

  • If I do not use generator methods and
    opt for using full list generator,
    then I will waste computation time
    doing nothing useful.

The solution was to try to deepcopy some specific generator methods, but I get errors.

It seems that the generators save references to, e.g. the vertices and edges of G and then when deepcopied to H the generators in H are still referencing the attributes of G (this sounds logical).

So, am I condemned to use deepcopy after all or not use generator methods?

Is there a third pythonic way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

晨曦÷微暖 2024-11-22 23:20:47

我很确定我明白你的意思。这是一个简单的例子:

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 时使迭代器无效之类的事情的方式,但我认为这应该相当简单。

I'm pretty sure I understand what you're getting at. Here's a simple example:

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()

Now of course this will print 1 1 2. You, however, want H.nodegen to remember the state of G.nodegen so that the call to H.nodegen.next() prints 2. A simple way is to make them the same object:

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)

This will print 1 2 3, since calling H.nodegen.next() will advance G.nodegen as well. If that's not what you want, it seems fine to me to keep an internal counter, like this:

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)

This will print 1 2 2, which I suspect is what you want. Of course you'll have to change how you take care of things like invalidating iterators when you change self.nodes, but I think it should be fairly straightforward.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文