Простое наследование питона - PullRequest
9 голосов
/ 17 июня 2011
class Animal(object):
    def __init__(self, nlegs=4):
        print '__init__ Animal'
        self.nlegs = nlegs

class Cat(Animal):
    def __init__(self, talk='meow'):
        print '__init__ Cat'
        self.talk = talk

class Dog(Animal):
    def __init__(self, talk='woof'):
        print '__init__ Dog'
        self.talk = talk
  1. Почему у моей кошки tom = Cat() нет атрибута nlegs?
  2. Должны ли мы явно вызывать Animal.__init__() изнутри Cat.__init__, или мы должны делать что-то более причудливое, скажем, с super?
  3. А если я хочу создать кошку с 5 ногами, нужно ли мне добавлять дополнительные аргументы в интерфейс Cat.__init__?

Ответы [ 3 ]

11 голосов
/ 17 июня 2011

Чтобы опираться на то, что сказали все остальные, да, вам нужно вызвать метод __init__ родителя.

Обычно лучше использовать супер. Тем не менее, в некоторых случаях (особенно когда вы наследуете от нескольких классов) это может быть большой ошибкой. Я не буду вдаваться в детали, нет недостатка в различных статьях, которые обсуждают это . (Кроме того, есть некоторые странности с некоторыми другими «специальными» функциями. Например, вы можете выполнить super(SomeCls, self).__getitem__(5), но super(SomeCls, self)[5] не будет работать.)

В качестве упрощенного примера того, почему это хорошая идея, вы можете сделать так, чтобы Dog и Cat наследовались от Mammal (который наследуется от Animal), и вам не пришлось бы менять места в вашем коде. чем класс Dog и Cat наследуется от.

Что касается того, почему ваш экземпляр tom не имеет tom.nlegs, это потому, что вы не вызвали Animal метод __init__.

Также помните, что не все нужно устанавливать во время инициализации. В этом примере имеет больше смысла не устанавливать такие вещи, как nlegs в методе __init__. Вместо этого просто установите его прямо в классе. Э.Г.

class Mammal(object):
    nlimbs = 4
    def __init__(self):
        print "I'm a mammal!"

class Cat(Mammal):
    def __init__(self, color="calico"):
        self.color = color
        super(Cat, self).__init__()
        print "I have {0} legs I am {1}".format(self.nlimbs, self.color)

class FiveLeggedCat(Cat):
    nlimbs = 5

В принципе, если что-то может измениться от экземпляра к экземпляру (например, цвет кота) или должно быть выполнено при инициализации (например, открытие файла), то это, вероятно, следует установить в __init__.

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

Кроме того, атрибуты, установленные таким образом, будут доступны инструментам документации (например, встроенной функции help), тогда как атрибуты, установленные при инициализации, не будут.

3 голосов
/ 17 июня 2011

Использование super:

class Cat(Animal):
    def __init__(self, talk='meow', num_legs=4):
        print 'Hay cat'
        self.talk = talk
        super(Cat, self).__init__(num_legs)


tom = Cat()  #tom is a normal cat
bob = Cat('Nyan', 3) #bob is a japanese defective cat
1 голос
/ 17 июня 2011

Вам нужно посмотреть документы Python о super().Например, вы обычно начинаете (или заканчиваете) свой метод Cat.__init__() вызовом super(Cat, self).__init__(<any args>).

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