Спадщина та метод init у Python


94

Я початківець python. Я не можу зрозуміти спадщину і __init__().

class Num:
    def __init__(self,num):
        self.n1 = num

class Num2(Num):
    def show(self):
        print self.n1

mynumber = Num2(8)
mynumber.show()

РЕЗУЛЬТАТ: 8

Це нормально. Але я замінюю Num2на

class Num2(Num):
    def __init__(self,num):
        self.n2 = num*2
    def show(self):
        print self.n1,self.n2

РЕЗУЛЬТАТ: Error. Num2 has no attribute "n1".

Як у цьому випадку Num2отримати доступ n1?

Відповіді:


148

У першій ситуації Num2це розширення класу, Numі оскільки ви не перевизначаєте спеціальний метод, названий __init__()в Num2, він успадковується від Num.

Коли клас визначає __init__() метод, екземпляр класу автоматично викликає __init__()новостворений екземпляр класу.

У другому випадку, так як ви переглядаєте __init__()в Num2вам потрібно явно викликати один в супер клас ( Num) , якщо ви хочете продовжити свою поведінку.

class Num2(Num):
    def __init__(self,num):
        Num.__init__(self,num)
        self.n2 = num*2

23
Вашого цитування недостатньо, щоб пояснити, чому, не визначаючи __init__метод у похідному класі, він успадковується. Це тому, що "якщо запитаний атрибут не знайдений у класі, пошук буде продовжено шукати в базовому класі". (doc)
eyquem

5
Вибачте ... в основному так працює успадкування ... якщо ви успадковуєте клас, ви отримуєте цілий пакет, отже, все в суперкласі існує в підкласі. Але якщо ви перевизначите метод, він буде перевизначений ... ось що є у вашому коді.
коя

4
@ mario-duarte будь-яка причина, чому це було б краще ніж super(Num2, self).__init__(num)?
guival

1
Я щойно перейшов із запропонованого у цій відповіді рішення на використання super, і моя програма зараз завантажується на кілька секунд швидше. Не знаю, чому.
Guimoute

superповинен бути корисним при використанні множинного успадкування. Для одиночного успадкування його переваги не очевидні.
Йоганн Бж



3

Проста зміна в класі Num2, як це:

super().__init__(num) 

Це працює в python3.

class Num:
        def __init__(self,num):
                self.n1 = num

class Num2(Num):
        def __init__(self,num):
                super().__init__(num)
                self.n2 = num*2
        def show(self):
                print (self.n1,self.n2)

mynumber = Num2(8)
mynumber.show()

1
Ось чому я люблю stackoverflow. Хоча це не відповідь на запитання, це корисно. Іноді відповіді, які люди публікують, - це відповіді на питання, яке люди мали б задавати. Дякую!
Глен Томпсон,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.