Python 递归地创建子类的副本?

Python 递归地创建子类的副本?,python,class,copy,Python,Class,Copy,类Event实现一个函数copyFrom(self,Event)和copy(self)。这两种方法的实现都很简单 class Event(object): def __init__(self, a, b): self.a = a self.b = b def copyFrom(self, event): self.a = event.a self.b = event.b def copy(self):

Event
实现一个函数
copyFrom(self,Event)
copy(self)
。这两种方法的实现都很简单

class Event(object):

    def __init__(self, a, b):
        self.a = a
        self.b = b

    def copyFrom(self, event):
        self.a = event.a
        self.b = event.b

    def copy(self):
        return Event(self.a, self.b)
现在,子类
MouseEvent
希望覆盖这两个类。第一个方法,
copyFrom(self,event)
可以通过调用super方法来实现

但是
复制(自我)
呢?当然,仅仅创建一个新对象并不难

    # ...
    def copy(self):
        return MouseEvent(self.a, self.b, self.c, self.d)
但是如果
事件
类拥有一些私有属性怎么办?想要将其子类化的人不想关心它们

class Event(object):

    def __init__(self, a, b):
        self.a = a
        self.b = b
        self._aab = fancyFunction(a, b)

    def doStuff(self, c):
        self._aab <<= c * 2

    def copyFrom(self, event):
        self.a = event.a
        self.b = event.b
        self._aab = event._aab

    def copy(self):
        e = Event(self.a, self.b)
        e._aab = self._aab
        return e

在这个特定的示例中,我如何实现一个简单的、可能是递归的复制行为?

首先,
MouseEvent
构造函数递归调用
事件
构造函数还不够吗

如果没有,请查看。它是基于。使用此协议,递归调用很容易。如果您不想遵循
pickle
接口,当然可以复制这个基本设计,因为我不认为这样做有任何好处

编辑:我似乎没能理解这个信息,事实上我的回答可能有点模糊。因此,我们在这里使用建议的设计进行代码示例:

class Event(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self._aab = fancyFunction(a, b)
    def retrieve_state(self):
        return self.a, self.b, self._aab
    def restore_state(self, state):
        self.a, self.b, self._aab = state
    def copy_from(self, event):
        self.restore_state(event.retrieve_state())
    def copy(self):
        e = object.__new__(self.__class__)
        e.restore_state(self.retrieve_state())
        return e

class MouseEvent(Event):    
    def __init__(self, a, b, c, d):
        Event.__init__(self, a, b)
        self.c = c
        self.d = d
    def retrieve_state(self):
        event_state = super(MouseEvent, self).retrieve_state()
        return event_state, self.c, self.d
    def restore_state(self, state):
        event_state, self.c, self.d = state
        super(MouseEvent, self).restore_state(event_state)

请注意,如果您只需分别将
retrieve\u state()
restore\u state()
重命名为
\u getstate\u()
\u setstate\u()
,您甚至不需要
copy\u from()
方法,因为这样做之后,您可以使用标准的
copy()
模块。(在本例中,您甚至不需要定义
\uuu getstate\uuuu()
\uu setstate\uuuu()
,因为默认行为是保存和恢复所有实例属性。)

但是,正如我所说的,如果
事件
-类拥有私有属性怎么办?请看一下(添加的)示例代码。对于
复制
模块,我需要再次创建一个函数
\uuuu复制
,不是吗?@NiklasR:1。行
e.\u aab=self.\u aab
是冗余的。该函数在调用之前调用
MouseEvent
构造函数,后者依次调用
Event()
,后者依次正确设置
e.\u aab
,因此没有问题。这就是我回答的第一句话的意思。2.如果您出于某种原因不喜欢这样做,请在类上实现
\uuu getstate\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()
\uu。它们中的每一个都可以调用相应的基类函数。这里的要点是将复制分为两部分,状态检索和状态恢复。这使得确保封装变得很容易。“行e.\u aab=self.\u aab是冗余的”-它不是冗余的,用户可以在调用
Event.doStuff(self,c)
时修改
\u aab
。实际上,我不明白这与酸洗有什么关系,对不起。@NiklasR:你问了一个如何在保持封装的同时实现实例复制的设计,我建议了一个在保持封装的同时实现实例复制的设计——即Python的
copy
模块的设计,顺便说一句,它依赖于
pickle
协议。此设计的中心点是状态检索和恢复的分离,这使得使用递归调用变得容易。您可以复制此设计并定义自己的状态检索和恢复协议,也可以使用
copy
模块经常使用的协议。啊哈!代码让我明白了!这真是个好设计。我会用的。非常感谢。
class MouseEvent(Event):

    # ...
    def copy(self):
        e = MouseEvent(self.a, self.b, self.c, self.d)
        e._aab = self._aab
        return e
class Event(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self._aab = fancyFunction(a, b)
    def retrieve_state(self):
        return self.a, self.b, self._aab
    def restore_state(self, state):
        self.a, self.b, self._aab = state
    def copy_from(self, event):
        self.restore_state(event.retrieve_state())
    def copy(self):
        e = object.__new__(self.__class__)
        e.restore_state(self.retrieve_state())
        return e

class MouseEvent(Event):    
    def __init__(self, a, b, c, d):
        Event.__init__(self, a, b)
        self.c = c
        self.d = d
    def retrieve_state(self):
        event_state = super(MouseEvent, self).retrieve_state()
        return event_state, self.c, self.d
    def restore_state(self, state):
        event_state, self.c, self.d = state
        super(MouseEvent, self).restore_state(event_state)