super(type, object-or-type)
type
- необязательно, тип, от которого начинается поиск объекта-посредникаobject-or-type
- необязательно, тип или объект, определяет порядок разрешения метода для поискаФункция super()
, возвращает объект объект-посредник, который делегирует вызовы метода родительскому или родственному классу, указанного type
типа. Это полезно для доступа к унаследованным методам, которые были переопределены в классе.
object-or-type
определяет порядок разрешения метода __mro__
для поиска. Поиск начинается с класса, сразу после указанного типа. Например, если __mro__
- это D -> B -> C -> A -> object
, а значение type=B
, то super()
выполняет поиск объекта C -> A -> object
.
object-or-type
не указан, то возвращается несвязанный объект-посредник.object-or-type
является объектом (экземпляром), то будет получен посредник, для которого isinstance(obj, type)
возвращает True
.object-or-type
является типом (классом), то будет получен посредник, для которого issubclass(subtype, type)
возвращает True
.Типичные случаи использования super()
:
В иерархиях с единичным наследованием используется для обращения к родительским классам, чтобы явно не указывать их имена, это упрощает поддержку кода в дальнейшем. Еще примеры.
Например:
>>> class A:
... def some_method(self):
... print('some_method A')
...
>>> class B(A):
... def some_method(self):
... print('some_method B')
...
>>> x = B()
>>> x.some_method()
# some_method B
Здесь перегружен метод родительского класса. Но что если необходимо немного дополнить родительский метод, не копируя его полностью? Тут и нужна функция super()
:
>>> class A:
... def some_method(self):
... print('some_method A')
...
>>> class B(A):
... def some_method(self):
... super().some_method()
... print('some_method B')
...
>>> x = B()
>>> x.some_method()
# some_method A
# some_method B
Для поддержки совместного множественного наследования в динамическом окружении. Он делает возможным обращение с ромбовидными иерархиями, при которых несколько базовых классов задают реализацию метода с одним и тем же именем.
Использование функция super()
с обоими аргументами точно определяет объекты и делает соответствующие ссылки. Без аргументов функция super()
работает только внутри определения класса, а необходимые детали для идентификации класса и доступа к текущему экземпляру для методов заполняет компилятор.
В дополнение к поиску методов, super()
также работает для поиска атрибутов. Одним из вариантов использования этого является вызов дескрипторов в родительском или родственном классе.
Обратите внимание, что super()
реализована как часть процесса привязки для явного поиска по точечным атрибутам, таких как super().__getitem__(name)
. Это достигается путем реализации собственного метода __getattribute__()
для поиска классов в предсказуемом порядке, который поддерживает кооперативное множественное наследование __mro__
. super()
и не предназначена для неявных поисков с использованием инструкций или операторов, таких как super()[name]
.
Функция в единичном наследовании:
class Computer():
def __init__(self, computer, ram, ssd):
self.computer = computer
self.ram = ram
self.ssd = ssd
# Если создать дочерний класс `Laptop`, то будет доступ
# к свойству базового класса благодаря функции super().
class Laptop(Computer):
def __init__(self, computer, ram, ssd, model):
super().__init__(computer, ram, ssd)
self.model = model
lenovo = Laptop('lenovo', 2, 512, 'l420')
print('This computer is:', lenovo.computer)
print('This computer has ram of', lenovo.ram)
print('This computer has ssd of', lenovo.ssd)
print('This computer has this model:', lenovo.model)
# Вывод
# This computer is: lenovo
# This computer has ram of 2
# This computer has ssd of 512
# This computer has this model: l420
В следующем примере класс Rectangle
является суперклассом, а Square
является подклассом, поскольку методы Square
наследуются от Rectangle
, то мы можем вызвать метод __init __()
суперкласса (Rectangle.__ init __()
) из класса Square
используя функцию super()
. Далее просто пользоваться методами родителя, не написав ни строчки кода. В данном случае квадрат - это частный случай прямоугольника...
class Rectangle:
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
return self.length * self.width
def perimeter(self):
return 2 * self.length + 2 * self.width
class Square(Rectangle):
def __init__(self, length):
# Для квадрата просто нужно передать один параметр length.
# При вызове 'super().__init__()' установим атрибуты 'length' и 'width'.
super().__init__(length, length)
# Класс 'Square' явно не реализует метод 'area()' и
# будет использовать его из суперкласса 'Rectangle'
sqr = Square(4)
print("Area of Square is:", sqr.area())
# Area of Square is: 16
rect = Rectangle(2, 4)
print("Area of Rectangle is:", rect.area())
# Area of Rectangle is: 8
И наконец пример работы функции super()
при использовании множественного наследования:
class A:
def __init__(self):
print('Initializing: class A')
def sub_method(self, b):
print('sub_method from class A:', b)
class B(A):
def __init__(self):
print('Initializing: class B')
super().__init__()
def sub_method(self, b):
print('sub_method from class B:', b)
super().sub_method(b + 1)
class X(B):
def __init__(self):
print('Initializing: class X')
super().__init__()
def sub_method(self, b):
print('sub_method from class X:', b)
super().sub_method(b + 1)
class Y(X):
def __init__(self):
print('Initializing: class Y')
# super() с параметрами
super(X, self).__init__()
def sub_method(self, b):
print('sub_method from class Y:', b)
super().sub_method(b + 1)
x = X()
x.sub_method(1)
print('Обратите внимание как происходит инициализация')
print('классов при указании аргументов в функции super()')
y = Y()
y.sub_method(5)
# Вывод
# Initializing: class X
# Initializing: class B
# Initializing: class A
# sub_method from class X: 1
# sub_method from class B: 2
# sub_method from class A: 3
# обратите внимание как происходит инициализация
# классов при указании аргументов в функции super()
# Initializing: class Y
# Initializing: class B
# Initializing: class A
# sub_method from class Y: 5
# sub_method from class X: 6
# sub_method from class B: 7
# sub_method from class A: 8