Ваш код не имеет ничего общего с порядком разрешения методов. Разрешение метода происходит в случае множественного наследования, что не относится к вашему примеру. Ваш код просто неверен, потому что вы предполагаете, что self.__class__
на самом деле является тем же классом, в котором определен метод, и это неправильно:
>>> class A(object):
... def __init__(self):
... print self.__class__
...
>>>
>>> class B(A):
... def __init__(self):
... A.__init__(self)
...
>>> B()
<class '__main__.B'>
<__main__.B object at 0x1bcfed0>
>>> A()
<class '__main__.A'>
<__main__.A object at 0x1bcff90>
>>>
поэтому, когда вы должны позвонить:
super(B, self).__init__(1, b, c)
вы действительно звоните:
# super(self.__class__, self).__init__(1, b, c)
super(C, self).__init__(1, b, c)
EDIT: попытка лучше ответить на вопрос.
class A(object):
def __init__(self, a):
for cls in self.__class__.mro():
if cls is not object:
cls._init(self, a)
def _init(self, a):
print 'A._init'
self.a = a
class B(A):
def _init(self, a):
print 'B._init'
class C(A):
def _init(self, a):
print 'C._init'
class D(B, C):
def _init(self, a):
print 'D._init'
d = D(3)
print d.a
печатает:
D._init
B._init
C._init
A._init
3
(Измененная версия шаблона).
Теперь методы родителей действительно вызываются неявно, но я должен согласиться с python zen, где явное лучше, чем неявное, потому что код менее читаем, а выигрыш плохой. Но имейте в виду, что все методы _init
имеют одинаковые параметры, полностью забыть о родителях нельзя, и я не советую этого делать.
Для одиночного наследования лучшим подходом является явный вызов родительского метода без вызова super
. При этом вам не нужно называть текущий класс, но вы все равно должны заботиться о том, кто является родительским классом.
Хорошие чтения: правильная вещь и ссылки, предложенные в этом вопросе, и, в частности, Python's Super отлично, но вы можете не использовать
Если иерархия может измениться, это является признаком плохого дизайна и имеет последствия для всех частей, которые используют этот код, и это не должно поощряться.
ИЗМЕНИТЬ 2
Мне приходит на ум другой пример, но в нем используются метаклассы. Библиотека Urwid использует метакласс для хранения атрибута __super
в классе, поэтому что вам нужно просто получить доступ к этому атрибуту.
Ex:
>>> class MetaSuper(type):
... """adding .__super"""
... def __init__(cls, name, bases, d):
... super(MetaSuper, cls).__init__(name, bases, d)
... if hasattr(cls, "_%s__super" % name):
... raise AttributeError, "Class has same name as one of its super classes"
... setattr(cls, "_%s__super" % name, super(cls))
...
>>> class A:
... __metaclass__ = MetaSuper
... def __init__(self, a):
... self.a = a
... print 'A.__init__'
...
>>> class B(A):
... def __init__(self, a):
... print 'B.__init__'
... self.__super.__init__(a)
...
>>> b = B(42)
B.__init__
A.__init__
>>> b.a
42
>>>
person
mg.
schedule
30.04.2010