Как правильно расширить метод родительского класса в современном Python? - PullRequest
21 голосов
/ 20 мая 2011

Я часто занимаюсь такими вещами:

class Person(object):
    def greet(self):
        print "Hello"

class Waiter(Person):
    def greet(self):
        Person.greet(self)
        print "Would you like fries with that?"

Строка Person.greet (self) кажется неправильной.Если я когда-нибудь изменю класс, от которого наследует Официант, мне придется отслеживать каждый из них и заменять их все.

Как правильно сделать это в современном Python?Как 2.x, так и 3.x, я понимаю, что в этой области произошли изменения в 3.

Если это имеет значение, я, как правило, придерживаюсь одиночного наследования, но если для корректного размещения множественного наследования требуются дополнительные вещи, это будетбудь хорошим, чтобы знать об этом.

Ответы [ 3 ]

20 голосов
/ 20 мая 2011

Вы используете super:

Возвращает прокси-объект, который делегирует вызовы метода родительского или родственного класса типа.Это полезно для доступа к унаследованным методам, которые были переопределены в классе.Порядок поиска такой же, как в getattr(), за исключением того, что сам тип пропускается.

Другими словами, вызов super возвращает поддельный объект, который делегирует поиск атрибутов классам вышеВы в цепочке наследования.Обратите внимание:

  • Это не работает с классами старого стиля - поэтому, если вы используете Python 2.x, вам нужно убедиться, что верхний класс в вашей иерархии наследуется от object.
  • Вам нужно передать свой собственный класс и экземпляр в super в Python 2.x.Это требование было отменено в 3.x.
  • Это будет правильно обрабатывать все множественное наследование.(Если у вас в Python есть дерево множественного наследования, генерируется порядок разрешения методов , и поиск проходит через родительские классы в этом порядке.)

Будьте осторожны: их многоместа, где можно запутаться в множественном наследовании в Python.Возможно, вы захотите прочитать super() Считается вредным .Если вы уверены, что собираетесь придерживаться одного дерева наследования и что вы не собираетесь изменять имена классов в указанном дереве, вы можете жестко закодировать имена классов, как вы делали выше, и все будет работать нормально.

9 голосов
/ 20 мая 2011

Не уверен, если вы ищете это, но вы можете позвонить родителю, не обращаясь к нему, сделав это.

super(Waiter, self).greet()

Это вызовет функцию greet() в Person.

4 голосов
/ 16 ноября 2011

Ответ katrielalex на самом деле является ответом на ваш вопрос, но он не подходит для комментария.

Если вы планируете использовать super везде, и вы когда-нибудь задумывались о множественном наследованииОбязательно прочитайте ссылку "super () Считается вредной"super() - отличный инструмент, но для правильного использования требуется понимание.По моему опыту, для простых вещей, которые, кажется, не могут попасть в сложные путаницы наследования алмазов, на самом деле проще и менее утомительно просто вызывать суперкласс напрямую и иметь дело с переименованиями, когда вы меняете имя базового класса.

Фактически, в Python2 вы должны включить текущее имя класса, которое, как правило, более вероятно изменится, чем имя базового класса.(И действительно, иногда очень трудно передать ссылку на текущий класс, если вы делаете дурацкие вещи; в момент, когда метод определен, класс не привязан ни к какому имени, а в момент, когда super вызов выполнен, оригинальное имя класса может все еще не привязываться к классу, например, когда вы используете декоратор класса)

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