Jak w Pythonie utworzyć podklasę z nadklasy?
Jak w Pythonie utworzyć podklasę z nadklasy?
Odpowiedzi:
# 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__()
super
, szczególnie w przypadku nowych programistów Pythona (np. Lutz). Unikam tego.
super
jest to, że nie rozumiesz różnic między tym, jak super
działa w Pythonie, a tym, jak super
/ parent
dział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ś.
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()
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
__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)
W powyższych odpowiedziach super
jest 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, list
która po zainicjowaniu natychmiast sortuje się w kierunku określonym przez reverse
argument 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 *args
do super
, lista może zostać zainicjowana i wypełniona pozycjami, a nie tylko pusta. (Należy pamiętać, że reverse
jest to argument zawierający tylko słowo kluczowe zgodnie z PEP 3102 ).
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.
Używasz:
class DerivedClassName(BaseClassName):
Szczegółowe informacje można znaleźć w dokumentacji Pythona, sekcja 9.5 .
class Mammal(object):
#mammal stuff
class Dog(Mammal):
#doggie stuff
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())