Python: Jak utworzyć podklasę z nadklasy?

86

Jak w Pythonie utworzyć podklasę z nadklasy?

dave.j.lott
źródło
3
Zauważ, że Python zmienił sposób, w jaki robisz podklasy, więc są na to dwa sposoby i nie mieszają się. Jeśli będziesz mieszać, pojawi się błąd. Przeczytaj ten post, aby zobaczyć różnicę: stackoverflow.com/questions/1713038/…
Mark Lakata

Odpowiedzi:

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

Lub jeszcze lepiej, użycie wbudowanej funkcji Pythonasuper() (zobacz dokumentację Python 2 / Python 3 ) może być nieco lepszą metodą wywołania rodzica w celu zainicjowania:

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

Lub dokładnie to samo, co powyżej, z wyjątkiem użycia postaci z zerowym argumentem super(), która działa tylko w definicji klasy:

class MySubClassBetter(MySuperClass):
    def __init__(self):
        super().__init__()
thompsongunner
źródło
6
OTOH, niektórzy ludzie przed nim ostrzegają super, szczególnie w przypadku nowych programistów Pythona (np. Lutz). Unikam tego.
eric
6
Jedynym powodem, którego należy unikać, superjest to, że nie rozumiesz różnic między tym, jak superdziała w Pythonie, a tym, jak super/ parentdziała w innych językach. Wprawdzie nie jest to oczywiste dla osób pochodzących z innych języków, ale nie doszedłbym do wniosku, że kwalifikuje to jako coś, przed czym należy „przestrzec”. To czyni pracę. Po prostu działa inaczej. Po prostu przeczytaj, co tak naprawdę robi w Pythonie, zanim zaczniesz narzekać na wyniki, których się nie spodziewałeś.
TheAtomicOption
3
Jaka jest różnica między nimi?
Tiwtiw
65

Bohaterski mały przykład:

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
źródło
37
class MySubClass(MySuperClass):
    def __init__(self):
        MySuperClass.__init__(self)

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

Odcinek od spadków w dokumentacji Pythona wyjaśnia to bardziej szczegółowo

Bryan Oakley
źródło
5
Musisz tylko zdefiniować tę __init__metodę, jeśli chcesz dodać do niej dalszy kod, w przeciwnym razie i tak zostanie użyta oryginalna metoda init (chociaż warto o tym wspomnieć i jest to całkowicie poprawny kod)
dbr
2
Myślę, że pytanie było na tyle niejasne, aby założyć, że może zostać dodany kolejny kod. Lepiej jest podać zbyt wiele informacji niż niewystarczających i zadać kolejne pytanie, gdy program operacyjny je wdroży. :)
Matt Dewey
15
class Class1(object):
    pass

class Class2(Class1):
    pass

Class2 jest podklasą Class1

workmad3
źródło
Fajne. Właśnie tego szukałem, tj. Podklasy bez rozszerzenia / nadpisań do super.
BuvinJ
9

W powyższych odpowiedziach superjest inicjowany bez żadnych argumentów (słów kluczowych). Często jednak chcesz to zrobić, a także przekazać własne „niestandardowe” argumenty. Oto przykład, który ilustruje ten przypadek użycia:

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

Jest to podklasa, listktóra po zainicjowaniu natychmiast sortuje się w kierunku określonym przez reverseargument słowa kluczowego, co ilustrują poniższe testy:

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__])

Dzięki przekazaniu *argsdo super, lista może zostać zainicjowana i wypełniona pozycjami, a nie tylko pusta. (Należy pamiętać, że reversejest to argument zawierający tylko słowo kluczowe zgodnie z PEP 3102 ).

Kurt Peek
źródło
4

Istnieje inny sposób dynamicznego tworzenia podklas w Pythonie za pomocą funkcji type():

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

Zwykle chcesz używać tej metody podczas pracy z metaklasami. Kiedy chcesz wykonać jakieś automatyzacje niższego poziomu, zmienia to sposób, w jaki Python tworzy klasę. Najprawdopodobniej nigdy nie będziesz musiał tego robić w ten sposób, ale kiedy to zrobisz, będziesz już wiedział, co robisz.

Pol
źródło
3
class Subclass (SuperClass):
      # Subclass stuff here
Wernsey
źródło
2
class Mammal(object): 
#mammal stuff

class Dog(Mammal): 
#doggie stuff
Chris Ballance
źródło
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())
Antiomic
źródło
5
Ta odpowiedź byłaby bardziej pomocna, gdybyś dołączył wyjaśnienie, co robi
grooveplex
4
Chociaż ten kod może pomóc w rozwiązaniu problemu, nie wyjaśnia, dlaczego i / lub jak odpowiada na pytanie. Zapewnienie tego dodatkowego kontekstu znacznie poprawiłoby jego długoterminową wartość edukacyjną. Proszę edytować swoje odpowiedzi, aby dodać wyjaśnienie, w tym, co stosuje się ograniczenia i założenia.
Toby Speight
2
Chociaż ten fragment kodu może rozwiązać problem, dołączenie wyjaśnienia naprawdę pomaga poprawić jakość Twojego posta. Pamiętaj, że odpowiadasz na pytanie do czytelników w przyszłości, a osoby te mogą nie znać powodów, dla których zaproponowałeś kod.
andreas
0

Podklasy w Pythonie są wykonywane w następujący sposób:

class WindowElement:
    def print(self):
        pass

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

Oto samouczek dotyczący języka Python, który zawiera również klasy i podklasy.

dmeister
źródło