Чтобы опираться на то, что сказали все остальные, да, вам нужно вызвать метод __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
), тогда как атрибуты, установленные при инициализации, не будут.