Dziedziczenie i metoda init w Pythonie


99

Jestem początkującym pytonem. Nie rozumiem dziedziczenia i __init__().

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

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

mynumber = Num2(8)
mynumber.show()

WYNIK: 8

To jest wporządku. Ale mogę wymienić Num2z

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

WYNIK: Error. Num2 has no attribute "n1".

W takim przypadku, jak można Num2uzyskać dostęp n1?

Odpowiedzi:


152

W pierwszej sytuacji Num2jest to rozszerzenie klasy, Numa ponieważ nie redefiniujesz metody specjalnej o nazwie __init__()w Num2, jest ona dziedziczona z Num.

Gdy klasa definiuje __init__() metodę, instancja klasy jest automatycznie wywoływana __init__()dla nowo utworzonej instancji klasy.

W drugiej sytuacji, ponieważ przedefiniowujesz __init__()w Num2, musisz jawnie wywołać tę z superklasy ( Num), jeśli chcesz rozszerzyć jej zachowanie.

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

27
Twój cytat nie jest wystarczający, aby wyjaśnić, dlaczego, gdy nie definiujesz __init__metody w klasie pochodnej, jest ona dziedziczona. Dzieje się tak, ponieważ „jeśli żądany atrybut nie zostanie znaleziony w klasie, wyszukiwanie będzie kontynuowane w celu wyszukania klasy bazowej”. (doc)
— eyquem,

6
Przepraszam ... tak w zasadzie działa dziedziczenie ... jeśli dziedziczysz klasę, otrzymujesz cały pakiet, więc wszystko w nadklasie istnieje w podklasie. Ale jeśli przedefiniujesz metodę, zostanie ona zastąpiona ... to właśnie jest w twoim kodzie.
— coya

5
@ mario-duarte jakiś powód, dla którego byłoby to lepsze niż super(Num2, self).__init__(num)?
— guival

1
Właśnie przełączyłem się z rozwiązania zaproponowanego w tej odpowiedzi na używanie super, a mój program ładuje się teraz o kilka sekund szybciej. Nie mam pojęcia dlaczego.
— Guimoute

superma być pomocny w przypadku dziedziczenia wielokrotnego. W przypadku pojedynczego spadku korzyści nie są oczywiste.
— Johann Bzh



4

Prosta zmiana w klasie Num2, taka jak ta:

super().__init__(num) 

Działa w 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()

2
Dlatego uwielbiam przepełnienie stosów. Chociaż to nie jest odpowiedź na pytanie, jest pomocna. Czasami odpowiedzi publikowane przez ludzi są odpowiedziami na pytanie, które ludzie powinni byli zadawać. Dziękuję Ci!
— Glen Thompson,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.