У Python, як створити підклас із суперкласу?
У Python, як створити підклас із суперкласу?
Відповіді:
# Initialize using Parent
#
class MySubClass(MySuperClass):
def __init__(self):
MySuperClass.__init__(self)
Або, ще краще, використання вбудованої функції Pythonsuper()
(див. Документацію до Python 2 / Python 3 для неї) може бути дещо кращим методом виклику батьків для ініціалізації:
# Better initialize using Parent (less redundant).
#
class MySubClassBetter(MySuperClass):
def __init__(self):
super(MySubClassBetter, self).__init__()
Або те саме саме, що і трохи вище, за винятком використання нульової форми аргументу super()
, яка працює лише всередині визначення класу:
class MySubClassBetter(MySuperClass):
def __init__(self):
super().__init__()
super
, особливо для нових програмістів на Python (наприклад, Lutz). Я уникаю цього.
super
це якщо ви не розумієте різниці між тим, як super
працює Python, і як super
/ parent
працює іншими мовами. Слід визнати, що це не очевидно для людей, які походять з інших мов, але я б не дійшов висновку, що це кваліфікує це як щось для "застереження". Це робить роботу. Це просто працює по-іншому. Просто прочитайте про те, що він насправді робить у Python, перш ніж скаржитися на отримання результатів, яких ви не очікували.
Маленький героїчний приклад:
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>
Розділ про спадкування в документації пітона пояснює це більш детально
__init__
метод, якщо ви хочете додати до нього подальший код, інакше в будь-якому випадку використовується оригінальний метод init (хоча про це варто згадати і цілком дійсний код)
У наведених вище відповідях значення super
ініціалізується без будь-яких аргументів (ключових слів). Однак часто ви хотіли б це зробити, а також передати власні "власні" аргументи. Ось приклад, який ілюструє цей варіант використання:
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
Це підклас, list
який при ініціалізації негайно сортує себе у напрямку, зазначеному reverse
аргументом ключового слова, як ілюструють наступні тести:
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__])
Завдяки переходить з *args
в super
список можна форматувати і заповнювати елементи замість тільки бути порожнім. (Зверніть увагу, що reverse
це аргумент лише для ключових слів відповідно до PEP 3102 ).
Існує ще один спосіб зробити підкласи в python динамічно за допомогою функції type()
:
SubClass = type('SubClass', (BaseClass,), {'set_x': set_x}) # Methods can be set, including __init__()
Зазвичай ви хочете використовувати цей метод під час роботи з метакласами. Коли ви хочете виконати деякі автоматизації нижчого рівня, це змінює спосіб створення python класу. Швидше за все, вам ніколи не потрібно буде робити це таким чином, але коли ви це зробите, тоді вже будете знати, що робите.
Ти використовуєш:
class DerivedClassName(BaseClassName):
Докладніше див. У документації Python, розділ 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())