все Python 3ООПпонятие
Множественное наследование / MRO
наследование
Python поддерживает множественное наследование. Порядок разрешения методов (MRO) — C3-линеаризация.
Синтаксис
class C(A, B): ...
C.__mro__
super() ведёт не к «родителю», а к следующему классу в __mro__, поэтому при кооперативном наследовании каждый __init__ обязан звать super().__init__() — иначе часть базовых классов молча не отработает. Если из баз нельзя построить непротиворечивый порядок (конфликт C3), Python бросит TypeError прямо на объявлении класса, а не при вызове метода.
Примеры
class A:
def hello(self):
return 'A'
class B:
def hello(self):
return 'B'
class C(A, B):
pass
print(C().hello()) # → A (первый в MRO)
print([c.__name__ for c in C.__mro__]) # → ['C', 'A', 'B', 'object']
# Diamond problem
class Base:
def method(self):
return 'Base'
class Left(Base):
def method(self):
return 'Left+' + super().method()
class Right(Base):
def method(self):
return 'Right+' + super().method()
class Diamond(Left, Right):
pass
print(Diamond().method()) # → Left+Right+Base (каждый Base вызывается раз!)
print([c.__name__ for c in Diamond.__mro__]) # → ['Diamond', 'Left', 'Right', 'Base', 'object']
# Mixin pattern
class JSONMixin:
def to_json(self):
import json
return json.dumps(self.__dict__)
class LogMixin:
def log(self):
print(f'{type(self).__name__}: {self.__dict__}')
class User(JSONMixin, LogMixin):
def __init__(self, name, age):
self.name = name
self.age = age
u = User('Alice', 30)
print(u.to_json()) # → {"name": "Alice", "age": 30}
# Проверка MRO
class X: pass
class Y(X): pass
class Z(X): pass
class W(Y, Z): pass
print([c.__name__ for c in W.__mro__]) # → ['W','Y','Z','X','object']
# super() в множественном наследовании
class A:
def f(self): return ['A']
class B(A):
def f(self): return ['B'] + super().f()
class C(A):
def f(self): return ['C'] + super().f()
class D(B, C):
def f(self): return ['D'] + super().f()
print(D().f()) # → ['D','B','C','A']
См. также
Открыть в полном глоссарииdocs.python.orgСообщить о неточности