Подтвердить что ты не робот

Каков правильный способ расширения метода родительского класса в современном Python

Я часто делаю такие вещи:

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.

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

super(Waiter, self).greet()

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

Ответ 3

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

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

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