Создать копию подкласса, рекурсивно? - PullRequest
1 голос
/ 20 ноября 2011

Класс 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 -метода.

class MouseEvent(Event):

    def __init__(self, a, b, c, d):
        super(Event, self).__init__(a, b)
        self.c = c
        self.d = d

    def copyFrom(self, event):
        super(Event, self).copyFrom(event)
        self.c = event.c
        self.d = event.d

Но как насчет copy(self)?Конечно, просто создать новый объект не сложно.

    # ...
    def copy(self):
        return MouseEvent(self.a, self.b, self.c, self.d)

Но что, если класс Event обладает некоторыми закрытыми атрибутами?Человек, который хочет подкласс этого, не хочет заботиться о них!

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

Эта реализация copy(self) выглядит довольно грязной, как и переопределенная реализация из MouseEvent.

class MouseEvent(Event):

    # ...
    def copy(self):
        e = MouseEvent(self.a, self.b, self.c, self.d)
        e._aab = self._aab
        return e

Как я могу реализовать простой, возможно, рекурсивный copy - Поведение в этом конкретном примере?

1 Ответ

3 голосов
/ 20 ноября 2011

Во-первых, разве недостаточно, чтобы конструктор MouseEvent рекурсивно вызывал конструктор Event?

Если нет, взгляните на модуль copy . Он основан на протоколе поиска и восстановления состояния pickle . Используя этот протокол, рекурсивные вызовы просты. Конечно, вы можете просто скопировать этот базовый дизайн, если не хотите соответствовать интерфейсу 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)

Обратите внимание, что вам даже не понадобятся методы copy() и copy_from(), если вы просто переименуете retrieve_state() и restore_state() в __getstate__() и __setstate__() соответственно, потому что после этого вы можете просто используйте стандартный модуль copy(). (И в данном случае вам даже не нужно было бы определять __getstate__() и __setstate__() вообще, поскольку поведение по умолчанию - сохранять и восстанавливать все атрибуты экземпляра.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...