Python: как создать подкласс из суперкласса?

86

Как в Python создать подкласс из суперкласса?

dave.j.lott
источник
3
Обратите внимание, что Python изменил способ создания подклассов, поэтому есть два способа сделать это, и они не смешиваются. Вы получите ошибку, если смешаете. Прочтите этот пост, чтобы увидеть разницу: stackoverflow.com/questions/1713038/…
Марк Лаката

Ответы:

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__()
Thompsongunner
источник
6
Некоторые люди предостерегают от OTOH, superособенно для начинающих программистов на Python (например, Lutz). Я этого избегаю.
Эрик
6
Единственная причина, по которой следует избегать, super- это если вы не понимаете различий между тем, как superработает в Python, и как super/ parentработает на других языках. По общему признанию, это не очевидно для людей, пришедших с других языков, но я бы не стал делать вывод, что это квалифицирует это как нечто, от чего следует «предостеречь». Это действительно работает. Просто это работает иначе. Просто прочтите о том, что он на самом деле делает в Python, прежде чем пожаловаться на получение неожиданных результатов.
TheAtomicOption
3
Какая разница между двумя?
Tiwtiw
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()
Ewall
источник
37
class MySubClass(MySuperClass):
    def __init__(self):
        MySuperClass.__init__(self)

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

Раздел о наследовании в документации питона объясняет это более подробно

Брайан Окли
источник
5
Вам нужно определить этот __init__метод только в том случае, если вы хотите добавить к нему дополнительный код, в противном случае исходный метод инициализации будет использоваться в любом случае (хотя об этом стоит упомянуть, и это совершенно действительный код)
dbr
2
Я думаю, вопрос был достаточно расплывчатым, чтобы предположить, что может быть добавлен дополнительный код. Лучше предоставить слишком много информации, чем недостаточно, и в конечном итоге возникнет другой вопрос, когда OP реализует его. :)
Мэтт Дьюи,
15
class Class1(object):
    pass

class Class2(Class1):
    pass

Class2 является подклассом Class1

workmad3
источник
Круто. Это то, что я действительно искал, то есть подкласс без расширения / переопределения для суперпользователя.
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__])

Благодаря передаче *argsto superсписок может быть инициализирован и заполнен элементами, а не только пустым. (Обратите внимание, что reverseэто аргумент, содержащий только ключевое слово, в соответствии с PEP 3102 ).

Курт Пик
источник
4

Есть еще один способ динамически создавать подклассы в python с помощью функции type():

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

Обычно вы хотите использовать этот метод при работе с метаклассами. Когда вы хотите выполнить автоматизацию более низкого уровня, это меняет способ создания классов в Python. Скорее всего, вам никогда не понадобится делать это таким образом, но когда вы это сделаете, вы уже будете знать, что делаете.

Pol
источник
3
class Subclass (SuperClass):
      # Subclass stuff here
Вернси
источник
2
class Mammal(object): 
#mammal stuff

class Dog(Mammal): 
#doggie stuff
Крис Балланс
источник
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, которое также содержит классы и подклассы.

dmeister
источник