Python: Bagaimana cara membuat subclass dari superclass?

86

Dengan Python, bagaimana Anda membuat subclass dari superclass?

dave.j.lott
sumber
3
Perhatikan bahwa Python mengubah cara Anda melakukan subclass, jadi ada 2 cara untuk melakukannya, dan mereka tidak dapat bercampur. Anda akan mendapatkan pesan kesalahan jika mencampur. Baca posting ini untuk melihat perbedaannya: stackoverflow.com/questions/1713038/…
Mark Lakata

Jawaban:

90
# Initialize using Parent
#
class MySubClass(MySuperClass):
    def __init__(self):
        MySuperClass.__init__(self)

Atau, lebih baik lagi, penggunaan fungsi bawaan Python , super()(lihat dokumentasi Python 2 / Python 3 untuk itu) mungkin merupakan metode yang sedikit lebih baik untuk memanggil induk untuk inisialisasi:

# Better initialize using Parent (less redundant).
#
class MySubClassBetter(MySuperClass):
    def __init__(self):
        super(MySubClassBetter, self).__init__()

Atau, sama persis seperti di atas, kecuali menggunakan bentuk argumen nol super(), yang hanya berfungsi di dalam definisi kelas:

class MySubClassBetter(MySuperClass):
    def __init__(self):
        super().__init__()
thompsongunner
sumber
6
OTOH, beberapa orang berhati-hati super, terutama untuk programmer Python baru (mis., Lutz). Saya menghindarinya.
eric
7
Satu-satunya alasan untuk menghindarinya superadalah jika Anda tidak memahami perbedaan antara cara superkerja Python, dan cara super/ parentkerja dalam bahasa lain. Memang ini tidak jelas bagi orang-orang yang berasal dari bahasa lain, tetapi saya tidak akan menyimpulkan bahwa hal itu memenuhi syarat sebagai sesuatu yang harus "diwaspadai". Ini tidak bekerja. Ini hanya bekerja secara berbeda. Baca saja tentang apa yang sebenarnya dilakukannya dengan Python sebelum Anda mengeluh tentang mendapatkan hasil yang tidak Anda harapkan.
TheAtomicOption
65

Contoh kecil heroik:

class SuperHero(object): #superclass, inherits from default object
    def getName(self):
        raise NotImplementedError #you want to override this on the child classes

class SuperMan(SuperHero): #subclass, inherits from SuperHero
    def getName(self):
        return "Clark Kent"

class SuperManII(SuperHero): #another subclass
    def getName(self):
       return "Clark Kent, Jr."

if __name__ == "__main__":
    sm = SuperMan()
    print sm.getName()
    sm2 = SuperManII()
    print sm2.getName()
ewall
sumber
37
class MySubClass(MySuperClass):
    def __init__(self):
        MySuperClass.__init__(self)

        # <the rest of your custom initialization code goes here>

The bagian tentang warisan dalam dokumentasi python menjelaskan hal itu secara lebih rinci

Bryan Oakley
sumber
5
Anda hanya perlu mendefinisikan __init__metode itu jika ingin menambahkan kode lebih lanjut, jika tidak metode init asli tetap digunakan (meskipun perlu disebutkan, dan merupakan kode yang benar-benar valid)
dbr
2
Saya pikir pertanyaan itu cukup samar untuk mengasumsikan mungkin ada kode lebih lanjut yang ditambahkan. Lebih baik memberikan terlalu banyak info daripada tidak cukup dan berakhir dengan pertanyaan lain saat OP mengimplementasikannya. :)
Matt Dewey
15
class Class1(object):
    pass

class Class2(Class1):
    pass

Kelas2 adalah sub-kelas dari Kelas1

workmad3
sumber
Keren. Inilah yang sebenarnya saya cari, yaitu sub kelas tanpa ekstensi / menimpa super.
BuvinJ
10

Dalam jawaban di atas, superini diinisialisasi tanpa argumen (kata kunci). Namun, sering kali Anda ingin melakukan itu, serta menyampaikan beberapa argumen 'kebiasaan' Anda sendiri. Berikut adalah contoh yang menggambarkan kasus penggunaan ini:

class SortedList(list):
    def __init__(self, *args, reverse=False, **kwargs):
        super().__init__(*args, **kwargs)       # Initialize the super class
        self.reverse = reverse
        self.sort(reverse=self.reverse)         # Do additional things with the custom keyword arguments

Ini adalah subkelas listyang, ketika diinisialisasi, langsung mengurutkan dirinya sendiri ke arah yang ditentukan oleh reverseargumen kata kunci, seperti yang diilustrasikan oleh pengujian berikut:

import pytest

def test_1():
    assert SortedList([5, 2, 3]) == [2, 3, 5]

def test_2():
    SortedList([5, 2, 3], reverse=True) == [5, 3, 2]

def test_3():
    with pytest.raises(TypeError):
        sorted_list = SortedList([5, 2, 3], True)   # This doesn't work because 'reverse' must be passed as a keyword argument

if __name__ == "__main__":
    pytest.main([__file__])

Berkat penerusan *argske super, daftar dapat diinisialisasi dan diisi dengan item, bukan hanya kosong. (Perhatikan bahwa reverseargumen hanya kata kunci sesuai dengan PEP 3102 ).

Kurt Peek
sumber
4

Ada cara lain untuk membuat subclass di python secara dinamis dengan fungsi type():

SubClass = type('SubClass', (BaseClass,), {'set_x': set_x})  # Methods can be set, including __init__()

Anda biasanya ingin menggunakan metode ini saat bekerja dengan metaclasses. Ketika Anda ingin melakukan otomatisasi tingkat yang lebih rendah, itu mengubah cara python membuat kelas. Kemungkinan besar Anda tidak perlu melakukannya dengan cara ini, tetapi ketika Anda melakukannya, Anda sudah akan tahu apa yang Anda lakukan.

Pol
sumber
3
class Subclass (SuperClass):
      # Subclass stuff here
Wernsey
sumber
3

Kau gunakan:

class DerivedClassName(BaseClassName):

Untuk detailnya, lihat dokumen Python, bagian 9.5 .

Reed Copsey
sumber
2
class Mammal(object): 
#mammal stuff

class Dog(Mammal): 
#doggie stuff
Chris Ballance
sumber
1
class BankAccount:

  def __init__(self, balance=0):
    self.balance = int(balance)

  def checkBalance(self): ## Checking opening balance....
    return self.balance

  def deposit(self, deposit_amount=1000): ## takes in cash deposit amount and updates the balance accordingly.
    self.deposit_amount = deposit_amount
    self.balance += deposit_amount
    return self.balance

  def withdraw(self, withdraw_amount=500): ## takes in cash withdrawal amount and updates the balance accordingly
    if self.balance < withdraw_amount: ## if amount is greater than balance return `"invalid transaction"`
        return 'invalid transaction'
    else:
      self.balance -= withdraw_amount
      return self.balance


class MinimumBalanceAccount(BankAccount): #subclass MinimumBalanceAccount of the BankAccount class

    def __init__(self,balance=0, minimum_balance=500):
        BankAccount.__init__(self, balance=0)
        self.minimum_balance = minimum_balance
        self.balance = balance - minimum_balance
        #print "Subclass MinimumBalanceAccount of the BankAccount class created!"

    def MinimumBalance(self):
        return self.minimum_balance

c = BankAccount()
print(c.deposit(50))
print(c.withdraw(10))

b = MinimumBalanceAccount(100, 50)
print(b.deposit(50))
print(b.withdraw(10))
print(b.MinimumBalance())
Antiomik
sumber
5
Jawaban ini akan lebih membantu jika Anda menyertakan penjelasan tentang fungsinya
grooveplex
4
Meskipun kode ini dapat membantu memecahkan masalah, kode ini tidak menjelaskan mengapa dan / atau bagaimana menjawab pertanyaan tersebut. Memberikan konteks tambahan ini secara signifikan akan meningkatkan nilai pendidikan jangka panjangnya. Harap edit jawaban Anda untuk menambahkan penjelasan, termasuk batasan dan asumsi apa yang berlaku.
Toby Speight
2
Meskipun cuplikan kode ini dapat menyelesaikan pertanyaan, menyertakan penjelasan sangat membantu meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa mendatang, dan orang-orang itu mungkin tidak tahu alasan saran kode Anda.
andreas
0

Subclassing dengan Python dilakukan sebagai berikut:

class WindowElement:
    def print(self):
        pass

class Button(WindowElement):
    def print(self):
        pass

Berikut adalah tutorial tentang Python yang juga berisi kelas dan subclass.

dmeister
sumber