Проблема заключается в том, что, написав super(MyClass, self).__init__(text)
, вы говорите, что используете суперсоответствие по отношению к любому классу MyClass
, к которому относится в то время, когда вызывается super
. Но декоратор заменяет MyClass
подклассом самого себя. Поэтому, когда ваш оригинальный метод __init__
называется MyClass
, фактически относится к подклассу класса, который определяет метод выполнения.
Чтобы сказать это шаг за шагом, я собираюсь назвать исходный класс (как указано в источнике) OrigMyClass
, а полученную версию (после декоратора) DecMyClass
. Я буду использовать MyClass
как переменную, потому что ее значение изменяется во время выполнения.
Вы определить __init__
метод на OrigMyClass
, но __init__
метод вызывает super(MyClass, self)
, не super(OrigMyClass, self)
. Таким образом, какой метод будет фактически называться, зависит от того, что MyClass
относится к во время вызова метода. Значение MyClass
проверяется во время выполнения, как и любая другая переменная; размещение его внутри вызова super
или внутри метода __init__
не магически привязывает его к классу, в котором он находится, когда вы его пишете; переменные в функциях вычисляются, когда они вызывается, а не когда они определены.
Декоратор работает. Декоратор определяет новый класс DecMyClass
как подкласс OrigMyClass
. DecMyClass
определяет __init__
, который вызывает super(DecMyClass, self)
.
После запуска декоратора имя MyClass
связано с классом DecMyClass
. Обратите внимание, что это означает, что когда вызов super(MyClass, self)
будет выполнен позже, он будет делать super(DecMyClass, self)
.
Когда вы делаете MyClass(111)
, вы создаете объект DecMyClass
. DecMyClass.__init__
звонки super(DecMyClass, self).__init__
. Это выполняет OrigMyClass.__init__
.
OrigMyClass.__init__
звонки super(MyClass, self).__init__
.Потому что MyClass
относится к DecMyClass
, это то же самое, что и super(DecMyClass, self).__init__
. Но DecMyClass
является подклассом OrigMyClass
. Ключевым моментом является то, что, поскольку MyClass
относится к DecMyClass
, OrigMyClass
на самом деле вызывает супер по подклассу самого себя.
Таким образом, super(DecMyClass, self).__init__
снова вызывает OrigMyClass.__init__
, который снова называет себя и так далее до бесконечности.
Эффект такой же, как этот код, который может сделать путь выполнения более очевидным:
>>> class Super(object):
... def __init__(self):
... print "In super init"
... super(Sub, self).__init__()
>>> class Sub(Super):
... def __init__(self):
... print "In sub init"
... super(Sub, self).__init__()
Обратите внимание, что Super
называет super(Sub, self)
. Он пытается вызвать метод суперкласса, но он пытается вызвать метод суперкласса Sub
. Суперкласс Sub
- Super
, поэтому Super
снова начинает свой собственный метод.
Edit: Только для уточнения вопросов имя-подстановок вы подняли, вот еще немного другой пример, который имеет тот же результат:
>>> class Super(object):
... def __init__(self):
... print "In super init"
... super(someClass, self).__init__()
>>> class Sub(Super):
... def __init__(self):
... print "In sub init"
... super(Sub, self).__init__()
>>> someClass = Sub
Это должно дать понять, что класс аргумент super
(первый аргумент , здесь someClass
) не является особенным. Это просто обычное имя, значение которого просматривается обычным способом в обычное время, а именно при выполнении вызова super
. Как показано в этом примере, переменная даже не должна существовать во время определения метода; значение отображается в то время, когда вы звоните метод.
Super() немного сложнее с python, проверьте http://rhettinger.wordpress.com/2011/05/26/super-considered-super/ – Lycha