Это подробно описано с достаточным количеством подробностей самим Гвидо в его посте « Постановление о разрешении метода» (включая две более ранние попытки).
В вашем примере Third()
позвоним First.__init__
. Python ищет каждый атрибут в родительских классах, поскольку они перечислены слева направо. В этом случае мы ищем __init__
. Итак, если вы определите
class Third(First, Second):
...
Python начнет с просмотра First
, и, если у First
него нет атрибута, он будет смотреть Second
.
Эта ситуация становится более сложной, когда наследование начинает пересекать пути (например, если First
наследуется от Second
). Прочитайте ссылку выше для получения более подробной информации, но, в двух словах, Python будет пытаться поддерживать порядок, в котором каждый класс появляется в списке наследования, начиная с самого дочернего класса.
Так, например, если у вас было:
class First(object):
def __init__(self):
print "first"
class Second(First):
def __init__(self):
print "second"
class Third(First):
def __init__(self):
print "third"
class Fourth(Second, Third):
def __init__(self):
super(Fourth, self).__init__()
print "that's it"
MRO будет [Fourth, Second, Third, First].
Кстати, если Python не может найти согласованный порядок разрешения методов, он вызовет исключение, вместо того чтобы вернуться к поведению, которое может удивить пользователя.
Отредактировано, чтобы добавить пример неоднозначного MRO:
class First(object):
def __init__(self):
print "first"
class Second(First):
def __init__(self):
print "second"
class Third(First, Second):
def __init__(self):
print "third"
Должно Third
быть MRO [First, Second]
или [Second, First]
? Нет очевидных ожиданий, и Python выдаст ошибку:
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution order (MRO) for bases Second, First
Редактировать: Я вижу, как несколько человек утверждают, что в приведенных выше примерах отсутствуют super()
вызовы, поэтому позвольте мне объяснить: цель примеров - показать, как строится MRO. Они не предназначены для печати "первая \ третья \ третья" или что-то еще. Вы можете - и, конечно, должны поиграться с этим примером, добавить super()
вызовы, посмотреть, что происходит, и глубже понять модель наследования Python. Но моя цель здесь состоит в том, чтобы сделать это простым и показать, как строится MRO. И это построено, как я объяснил:
>>> Fourth.__mro__
(<class '__main__.Fourth'>,
<class '__main__.Second'>, <class '__main__.Third'>,
<class '__main__.First'>,
<type 'object'>)
super()
есть какое-либо применение. Я не рекомендовал бы использовать это с классами, использующими линейное наследование, где это просто бесполезные накладные расходы.