Python: Як мені зробити підклас із суперкласу?


86

У Python, як створити підклас із суперкласу?


3
Зверніть увагу, що Python змінив спосіб підкласування, тому існує 2 способи зробити це, і вони не поєднуються. Ви отримаєте помилку, якщо змішаєте. Прочитайте цю статтю , щоб побачити різницю: stackoverflow.com/questions/1713038 / ...
Mark Lakata

Відповіді:


89
# 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__()

6
ОТО, деякі люди застерігають super, особливо для нових програмістів на Python (наприклад, Lutz). Я уникаю цього.
eric

6
Єдина причина, якої слід уникати, superце якщо ви не розумієте різниці між тим, як superпрацює Python, і як super/ parentпрацює іншими мовами. Слід визнати, що це не очевидно для людей, які походять з інших мов, але я б не дійшов висновку, що це кваліфікує це як щось для "застереження". Це робить роботу. Це просто працює по-іншому. Просто прочитайте про те, що він насправді робить у Python, перш ніж скаржитися на отримання результатів, яких ви не очікували.
TheAtomicOption

3
Яка різниця між ними?
Тівтів


65

Маленький героїчний приклад:

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()

37
class MySubClass(MySuperClass):
    def __init__(self):
        MySuperClass.__init__(self)

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

Розділ про спадкування в документації пітона пояснює це більш детально


5
Вам потрібно лише визначити цей __init__метод, якщо ви хочете додати до нього подальший код, інакше в будь-якому випадку використовується оригінальний метод init (хоча про це варто згадати і цілком дійсний код)
dbr

2
Я думаю, що питання було досить розмитим, щоб припустити, що може бути доданий подальший код. Краще надати занадто багато інформації, ніж недостатньо, і в кінцевому підсумку з’явиться ще одне запитання, коли ОП реалізує її. :)
Метт Дьюї

15
class Class1(object):
    pass

class Class2(Class1):
    pass

Class2 - це підклас Class1


Класно. Це те, що я насправді шукав, тобто підклас без розширення / заміни на супер.
BuvinJ

9

У наведених вище відповідях значення 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 ).


4

Існує ще один спосіб зробити підкласи в python динамічно за допомогою функції type():

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

Зазвичай ви хочете використовувати цей метод під час роботи з метакласами. Коли ви хочете виконати деякі автоматизації нижчого рівня, це змінює спосіб створення python класу. Швидше за все, вам ніколи не потрібно буде робити це таким чином, але коли ви це зробите, тоді вже будете знати, що робите.





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())

5
Ця відповідь була б більш корисною, якби ви включили пояснення того, що вона робить
grooveplex

4
Хоча цей код може допомогти вирішити проблему, він не пояснює, чому та / або як він відповідає на питання. Забезпечення цього додаткового контексту суттєво покращило б його довгострокову освітню цінність. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення, включаючи обмеження та припущення.
Тобі Спейт

2
Незважаючи на те, що цей фрагмент коду може вирішити питання, включення пояснення дійсно допомагає поліпшити якість вашої публікації. Пам’ятайте, що ви будете відповідати на запитання для читачів у майбутньому, і ці люди можуть не знати причин вашої пропозиції коду.
andreas

0

Підкласифікація в Python виконується наступним чином:

class WindowElement:
    def print(self):
        pass

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

Ось підручник про Python, який також містить класи та підкласи.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.