Как `super` взаимодействует с атрибутом класса __mro__ в множественном наследовании?
Сегодня я прочиталофициальный документ супер.
В котором упоминается множественное наследование, будет решаться__mro__
атрибут класса.
Я немного поэкспериментировал, но результат меня удивил.
# CODE PART
class GrandFather(object):
def p(self):
print "I'm old."
class Father(GrandFather):
def p(self):
print "I'm male."
class Mother(object):
def p(self):
print "I'm female."
class Son(Father, Mother):
def p(self):
print "busy, busy, crwaling. "
# EXPERIMENT PART
In [1]: Son.__mro__
Out[1]: (__main__.Son, __main__.Father, __main__.GrandFather, __main__.Mother, object)
In [2]: Father.__mro__
Out[2]: (__main__.Father, __main__.GrandFather, object)
In [3]: Mother.__mro__
Out[3]: (__main__.Mother, object)
In [4]: GrandFather.__mro__
Out[4]: (__main__.GrandFather, object)
In [5]: s = Son()
In [6]: super(Son, s).p()
I'm male.
In [7]: super(Father, s).p()
I'm old.
In [8]: super(Mother, s).p()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-ce4d0d6ef62d> in <module>()
----> 1 super(Mother, s).p()
AttributeError: 'super' object has no attribute 'p'
In [9]: super(GrandFather, s).p()
I'm female.
Ниже приведена часть официального документа, о котором я упоминал выше:
super(type[, object-or-type])
Return a proxy object that delegates method calls to a parent or sibling class of type.
This is useful for accessing inherited methods that have been overridden in a class.
The search order is same as that used by getattr() except that the type itself is skipped.
The __mro__ attribute of the type lists the method resolution search order
used by both getattr() and super().
The attribute is dynamic and can change whenever the inheritance hierarchy is updated.
If the second argument is an object, isinstance(obj, type) must be true.
Объединив этот документ и результат моего эксперимента. Самое запутанное, что при звонке сsuper(GrandFather, s).p()
это вызываетp()
изMother
, ноMother
не вGrandFather
«s__mro__
и это на очень низком уровнеSon
«s__mro__
.
После небольшого размышления. Я получил правдоподобное объяснение, которое указывает на неполноту или недостаток официального документа:
То есть при использовании сsuper(type, instance)
,super
функция будет искать из__mro__
атрибутclass
от того, кто твойinstance
это построить, но не__mro__
атрибутtype
ты перешел наsuper
, даже если он удовлетворяетisinstance(instance, type)
состояние.
Итак, что случилось, когда вы напечаталиsuper(Class, instance)
является:
isinstance(instance, Class)
правда.Python найти__class__
атрибутinstance
,получить
instance.__class__
«s__mro__
приписывать.Python найти индексClass
ты перешел наsuper
в__mro__
кортеж в шаге 2.Python добавить индекс шага 3 на 1, использовать его, чтобы получить соответствующий класс в__mro__
кортеж шага 2 и возврат супер-делегата этого соответствующего класса.Если индекс в шаге 4 превышает длину__mro__
Step2, делегат последнего класса в__mro__
шага 2 возвращается, который являетсяobject
учебный класс.Правильно ли мое понимание?
Если я ошибаюсь, какой правильный механизмsuper
взаимодействует сtype
«s__mro__
?
Если я прав, как мне поднять проблему для официальной модификации документа на python?
Потому что я думаю, что текущая версия об этом элементе может вводить в заблуждение.
PS: этот тест был сделанPython 2.7.6 within IPython 3.2.1
.