Я использую Python 2.5, поэтому этот вопрос может не относиться к Python 3. Когда вы создаете иерархию алмазных классов с использованием множественного наследования и создаете объект самого производного класса, Python поступает правильно (TM). Он вызывает конструктор для самого производного класса, затем его родительские классы, перечисленные слева направо, затем прародитель. Я знаком с MRO Python; это не мой вопрос. Мне любопытно, как объекту, возвращенному из super, на самом деле удается общаться с вызовами super в родительских классах в правильном порядке. Рассмотрим этот пример кода:
#!/usr/bin/python
class A(object):
def __init__(self): print "A init"
class B(A):
def __init__(self):
print "B init"
super(B, self).__init__()
class C(A):
def __init__(self):
print "C init"
super(C, self).__init__()
class D(B, C):
def __init__(self):
print "D init"
super(D, self).__init__()
x = D()
Код делает интуитивно понятную вещь, он печатает:
D init
B init
C init
A init
Однако, если вы закомментируете вызов super в функции инициализации B, ни функция инициализации A, ни C не будет вызвана. Это означает, что вызов B super каким-то образом знает о существовании C в общей иерархии классов. Я знаю, что super возвращает прокси-объект с перегруженным оператором get, но как объект, возвращаемый super в определении инициализации D, сообщает о существовании C объекту, возвращаемому super в определении инициализации B? Сохраняется ли информация о последующих вызовах супериспользования на самом объекте? Если да, то почему не super вместо self.super?
Редактировать: Jekke совершенно справедливо указал, что это не self.super, потому что super является атрибутом класса, а не экземпляром класса. Концептуально это имеет смысл, но на практике super также не является атрибутом класса! Вы можете проверить это в интерпретаторе, создав два класса A и B, где B наследуется от A, и вызвав dir(B)
. У него нет атрибутов super
или __super__
.
super()
определенно ведет себя по-другому в Python. Я оставлю остальную часть своего ответа для справки ниже: Публикую как ответ, потому что он слишком велик для комментария: теперь, когда я снова смотрю на него, и имейте в виду, что у меня нет под рукой переводчика , разве вы не ожидаете увидеть: D init B init C init A init в любом случае, потому чтоC
все равно будет вызыватьsuper()
? Во всяком случае, я считаю, что такое поведение можно объяснить тем, что все должны знать, чтоD
я - person Andy Mikula   schedule 03.03.2009