Metode pewarisan dan init dengan Python

94

Saya pemula dari python. Saya tidak dapat memahami warisan dan __init__().

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

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

mynumber = Num2(8)
mynumber.show()

HASIL: 8

Ini bagus. Tapi saya ganti Num2dengan

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

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

Dalam hal ini, bagaimana cara Num2mengakses n1?

Yugo Kamo
sumber

Jawaban:

148

Dalam situasi pertama, Num2memperpanjang kelas Numdan karena Anda tidak mendefinisikan ulang metode khusus bernama __init__()di Num2, itu akan diwarisi dari Num.

Ketika sebuah kelas mendefinisikan sebuah __init__() metode, instantiasi kelas secara otomatis memanggil __init__()instance kelas yang baru dibuat.

Dalam situasi kedua, karena Anda mendefinisikan ulang __init__()di Num2Anda perlu secara eksplisit memanggil satu di kelas super ( Num) jika Anda ingin memperpanjang perilakunya.

class Num2(Num):
    def __init__(self,num):
        Num.__init__(self,num)
        self.n2 = num*2
Mario Duarte
sumber
23
Kutipan Anda tidak cukup untuk menjelaskan mengapa, saat tidak mendefinisikan __init__metode dalam kelas turunan, kutipan itu akan diwarisi. Itu karena "jika atribut yang diminta tidak ditemukan di kelas, pencarian dilanjutkan untuk mencari di kelas dasar." (doc)
eyquem
5
Maaf ... pada dasarnya cara kerja pewarisan ... jika Anda mewarisi kelas, Anda mendapatkan seluruh paket, jadi, semua yang ada di kelas super ada di subkelas. Tapi, jika Anda mendefinisikan ulang metode, itu akan diganti ... itulah yang ada di kode Anda.
coya
4
@ mario-duarte ada alasan mengapa ini lebih baik daripada super(Num2, self).__init__(num)?
guival
1
Saya baru saja beralih dari solusi yang diusulkan dalam jawaban ini ke penggunaan super, dan program saya sekarang memuat beberapa detik lebih cepat. Tidak tahu kenapa.
Guimoute
superseharusnya berguna saat menggunakan banyak warisan. Untuk warisan tunggal, manfaatnya tidak jelas.
Johann Bzh
4

Karena Anda tidak menelepon Num.__init__, bidang "n1" tidak pernah dibuat. Sebut saja dan kemudian akan ada di sana.

Danny Milosavljevic
sumber
3

Perubahan sederhana di kelas Num2 seperti ini:

super().__init__(num) 

Ia bekerja di 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()
Sacchit Jaiswal
sumber
1
Inilah mengapa saya suka stackoverflow. Meskipun ini bukan jawaban untuk pertanyaan itu, itu membantu. Terkadang jawaban yang diposting orang adalah jawaban atas pertanyaan yang seharusnya ditanyakan orang. Terima kasih!
Glen Thompson