Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The problem is that by writing <code>super(MyClass, self).__init__(text)</code>, you are saying to use the super relative to whatever class <code>MyClass</code> refers to at the time <code>super</code> is called. But the decorator replaces <code>MyClass</code> with a subclass of itself. So when your original <code>__init__</code> method is called <code>MyClass</code> actually refers to a subclass of the class which defines the executing method.</p> <p>To say it step by step, I'm going to call the original class (as written in the source) <code>OrigMyClass</code>, and the resulting version (after the decorator) <code>DecMyClass</code>. I'll use <code>MyClass</code> just as a variable, because its meaning changes during the course of execution.</p> <ol> <li><p>You define an <code>__init__</code> method on <code>OrigMyClass</code>, but that <code>__init__</code> method calls <code>super(MyClass, self)</code>, not <code>super(OrigMyClass, self)</code>. Thus, what method will actually be called depends on what <code>MyClass</code> refers to <em>at the time the method is called</em>. The value of <code>MyClass</code> is looked up at execution time like any other variable; placing it inside the <code>super</code> call or inside the <code>__init__</code> method does not magically bind it to the class it happens to be in when you write it; variables in functions are evaluated when they are called, not when they are defined.</p></li> <li><p>The decorator runs. The decorator defines a new class <code>DecMyClass</code> as a subclass of <code>OrigMyClass</code>. <code>DecMyClass</code> defines an <code>__init__</code> that calls <code>super(DecMyClass, self)</code>.</p></li> <li><p>After the decorator runs, the name <code>MyClass</code> is bound to the class <code>DecMyClass</code>. Note that this means that when the <code>super(MyClass, self)</code> call later executes, it will be doing <code>super(DecMyClass, self)</code>.</p></li> <li><p>When you do <code>MyClass(111)</code>, you instantiate an object of <code>DecMyClass</code>. <code>DecMyClass.__init__</code> calls <code>super(DecMyClass, self).__init__</code>. This executes <code>OrigMyClass.__init__</code>.</p></li> <li><p><code>OrigMyClass.__init__</code> calls <code>super(MyClass, self).__init__</code>. Because <code>MyClass</code> refers to <code>DecMyClass</code>, this is the same as <code>super(DecMyClass, self).__init__</code>. But <code>DecMyClass</code> is a subclass of <code>OrigMyClass</code>. The key point is that because <code>MyClass</code> refers to <code>DecMyClass</code>, <code>OrigMyClass</code> is actually calling super <em>on a subclass of itself</em>.</p></li> <li><p>Thus <code>super(DecMyClass, self).__init__</code> again calls <code>OrigMyClass.__init__</code>, which again calls itself, and so on to infinity.</p></li> </ol> <p>The effect is the same as this code, which may make the execution path more obvious:</p> <pre><code>&gt;&gt;&gt; class Super(object): ... def __init__(self): ... print "In super init" ... super(Sub, self).__init__() &gt;&gt;&gt; class Sub(Super): ... def __init__(self): ... print "In sub init" ... super(Sub, self).__init__() </code></pre> <p>Note that <code>Super</code> calls <code>super(Sub, self)</code>. It is trying to call a superclass method, but it tries to call the superclass method of <code>Sub</code>. The superclass of <code>Sub</code> is <code>Super</code>, so <code>Super</code> winds up calling its own method again.</p> <p>Edit: Just to clarify the name-lookup issues you raised, here's another slightly different example that has the same result:</p> <pre><code>&gt;&gt;&gt; class Super(object): ... def __init__(self): ... print "In super init" ... super(someClass, self).__init__() &gt;&gt;&gt; class Sub(Super): ... def __init__(self): ... print "In sub init" ... super(Sub, self).__init__() &gt;&gt;&gt; someClass = Sub </code></pre> <p>This should make it clear that the class argument to <code>super</code> (the first argument, here <code>someClass</code>) is not special in any way. It is just an ordinary name whose value is looked up in the ordinary way at the ordinary time, namely when the <code>super</code> call is executed. As shown by this example, the variable doesn't even have to exist at the time you define the method; the value is looked up at the time you <em>call</em> the method.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload