Все классы (новый стиль) имеют линеаризованный порядок разрешения метода (MRO). В зависимости от дерева наследования, фактически вычисление MRO может быть немного разумом, но оно детерминировано через relatively simple algorithm. super
получает делегата на следующий класс в MRO. В вашем примере, Friend
имеет следующий MRO:
Friend -> Contact -> AddressHolder -> object
Если вы звоните супер в на из Friend
«методов s, вы получите доверитель, что делегаты Contact
» s методы. Если этот метод не вызывает super
, вы никогда не будете называть методы на AddressHolder
. Другими словами, super
отвечает за вызов только следующего метода в MRO, а не ALL остальных методов в MRO.
Это все хорошо, так как object
имеет полностью функциональный __init__
метод (так долго, как **kwargs
пусто в этой точке). К сожалению, он не работает, если вы пытаетесь разрешить цепочку вызовов какого-либо настраиваемого метода. например foo
. В этом случае вы хотите вставить базовый класс, на который наследуются все базовые классы. Поскольку этот класс является базой для всех классов (или, по крайней мере, базовых классов) для наследования. Этот класс будет в конечном итоге в конце MRO и может сделать параметр проверки :
class FooProvider:
def foo(self, **kwargs):
assert not kwargs # Make sure all kwargs have been stripped
class Bar(FooProvider):
def foo(self, x, **kwargs):
self.x = x
super().foo(**kwargs)
class Baz(FooProvider):
def foo(self, y, **kwargs):
self.y = y
super().foo(**kwargs)
class Qux(Bar, Baz):
def foo(self, z, **kwargs):
self.z = z
super().foo(**kwargs)
демо:
>>> q = Qux()
>>> q.foo(x=1, y=2, z=3)
>>> vars(q)
{'z': 3, 'y': 2, 'x': 1}
>>> q.foo(die='invalid')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() missing 1 required positional argument: 'z'
>>>
>>> q.foo(x=1, y=2, z=3, die='invalid')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/google/home/mgilson/sandbox/super_.py", line 18, in foo
super().foo(**kwargs)
File "/usr/local/google/home/mgilson/sandbox/super_.py", line 8, in foo
super().foo(**kwargs)
File "/usr/local/google/home/mgilson/sandbox/super_.py", line 13, in foo
super().foo(**kwargs)
File "/usr/local/google/home/mgilson/sandbox/super_.py", line 3, in foo
assert not kwargs # Make sure all kwargs have been stripped
AssertionError
Обратите внимание, вы все равно можете иметь аргументы по умолчанию с этим подходом, чтобы вы дон Там слишком много.
Заметим, что это не единственная стратегия, чтобы справиться с этой проблемой - Есть и другие подходы, которые можно предпринять при принятии Примеси, и т.д., но это, безусловно, самый надежный подход.
afaik он называет следующий пункт в стеке MRO .... –