DevGang
Авторизоваться

Python super() против метода Base.__init__

При определении подкласса существуют разные способы вызова метода __init__ родительского класса. Давайте начнем с базового класса и рассмотрим каждый из этих методов.

Для этого блога лучше открыть файл Python sample.py и следовать инструкциям.

class Base(object):
    def __init__ (self):
        print "Base created"

Метод 1: Непосредственное использование родительской ссылки

class ChildA(Base):
    def __init__ (self):
        Base. __init__ (self)
        print ("Child A initlaized")

Метод 2: Использование Super с дочерним классом

class ChildB(Base):
    def __init__ (self):
        print ("Child B initlaized")
        super(ChildB, self). __init__ ()

Метод 3: Использование супер-метода.

class ChildC(Base):
    def __init__ (self):
        super(). __init__ ()
        print ("Child C initlaized")

Вопросы

  • Каковы плюсы и минусы каждого метода?
  • Есть ли один-единственный правильный способ сделать это?

Когда вы запустите этот код как один скрипт Python, инициализируя дочерние классы A, B и C, вы не заметите абсолютно никакой разницы.

cA = ChildA()
cB = ChildB()
cC = ChildC()

Как мы можем демистифицировать это? Начнем с документации.

  • Начиная с Python3, super() аналогичен super(ChildB, self).__init__(). Это исключает один из трех методов.
  • Чтобы сравнить Base.__init__(self) и super().__init__(), нам нужно множественное наследование. Рассмотрим следующий фрагмент:
class Base1:
    def __init__ (self):     
        print ("Base 1 created")     
        super(). __init__ ()

class Base2:
    def __init__ (self):     
        print ("Base 2created")     
        super(). __init__ ()

Давайте напишем подклассы

class A1(Base1, Base2):
    def __init__ (self):     
        print ("Child A1 Initialized")     
        super(). __init__ ()

class A2(Base2, Base1):
    def __init__ (self):     
        print ("Child A Initialized")     
        super(). __init__ ()

Давайте инициализируем объекты

a1 = A1()
print ("\n\n")
a2 = A2()

Запустив приведенный выше фрагмент, мы получим следующий вывод:

Base 1 created
Base 2 created
Child A1 initialized

Base 2 created
Base 1 created
Child A2 initialized

В случае класса A1(Base1, Base2) первым инициализируется Base1, а затем Base2. Это противоположность классу А2. Можно сделать вывод, что методы вызываются в зависимости от порядка спецификации.

  • Когда вы используете метод Base1.__init__(), вы теряете эту возможность Python.
  • Когда вы введете новые иерархии, переименование классов станет кошмаром.

Итак, как Python узнает, какую функцию вызывать первой, вводя MRO (порядок разрешения метода)

Порядок разрешения метода

Порядок разрешения метода (MRO) обозначает способ, которым язык программирования разрешает метод или атрибут.

В случае одиночного наследования атрибут ищется только на одном уровне, при множественном наследовании интерпретатор Python ищет атрибут сам по себе, а затем его родительские элементы в порядке наследования. В случае A1 -> Base 1 -> Base 2.

Можно использовать функцию mro, чтобы найти порядок разрешения методов любого конкретного класса.

print (A2.mro())

** Output**

[<class ' __main__.A2'>, <class ' __main__.Base2'>, <class ' __main__.Base1'>, <class 'object'>]

Последний удар

Закомментируйте супер-вызовы в базовом классе и проверьте результат вашего скрипта.

class Base1:
    def __init__ (self):
        print ("Base 1 created")
        # super(). __init__ () 

class Base2:
    def __init__ (self):
        print ("Base 2 created")
        # super(). __init__ ()

Что ты видишь?

Base 1 created
Child A1 initlaized
Base 2 created
Child A2 initlaized

[<class ' __main__.A2'>, <class ' __main__.Base2'>, <class ' __main__.Base1'>, <class 'object'>]

Несмотря на наличие Base1 и Base2 в списке MRO, mro не выполнит порядок, если функция super() не будет распространена до базового класса, т. е. Python распространяет поиск атрибута только до тех пор, пока не найдет его. . Прокомментируйте метод init в Base1 и убедитесь сами.

class Base1:
    pass

    # def __init__ (self):
    # self.prop1 = "Base 1"
    # self.prop11 = "Base 11"
    # print ("Base 1 created")
    # # super(). __init__ ()

На выход

Поскольку Python не может найти метод __init__ в Base1, он проверяет Base2, прежде чем отправить его в класс объекта.

Base 2 created
Child A1 initlaized

Base 2 created
Child A2 initlaized
[<class ' __main__.A2'>, <class ' __main__.Base2'>, <class ' __main__.Base1'>, <class 'object'>]

Люди спрашивают меня, почему я так люблю Python. Это не потому, что Python прост и удобен. Все эти вещи Python делает для того, чтобы облегчить нам задачу, а иногда и немного усложнить :)

Источник:

#Flask #Python #Django
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу