another super wart

Michele Simionato mis6 at pitt.edu
Wed Mar 12 15:26:39 CET 2003


I have found a very subtle problem (bug?) with super used in conjunction
with __new__. It does not do what I expect.

First of all, let me explain what I expect.

Consider an ancestor class with a new static method

>>> class A(object):
...    def new(): print 'A.new'
...    new=staticmethod(new)

and a custom metaclass with a different static method new

>>> class Type(type): 
...    def new(): print 'Type.new'
...    new=staticmethod(new)

Now derive a base class B from A

>>> class B(A): pass

and a metaclass M from B and Type:
    
>>> class M(B,Type): pass

Finally, let me create an instance of M with base B:
    
>>> C=M('C',(B,),{})

Now let me invoke

>>> super(B,C).new()
A.new 

This is correct, since the parent of B is A. This means that

>>> super(B,C).new is A.new
True
>>> super(B,C).new is not Type.new
True

Nevertheless for the __new__ staticmethod I obtain something completely
different!!

>>> super(B,C).__new__ is A.__new__
False
>>> super(B,C).__new__ is not Type.__new__
False

How is it possible?? It seems that __new__ is very special and behaves
in the opposite way of new! (__init__ instead would work as expected).

Fortunately, there is a workaround, to call super with a C instance:

>>> super(B,C()).__new__ is A.__new__
True
>>> super(B,C()).__new__ is not Type.__new__
True

Unfortunately, I cannot use this in my program since super is called inside
__new__, before the instantiation of C. Discovering this very subtle 
inconsistency (which I would call a bug in the implementation of super) 
made me loose an afternoon :-(

--
Michele Simionato - Dept. of Physics and Astronomy
210 Allen Hall Pittsburgh PA 15260 U.S.A.
Phone: 001-412-624-9041 Fax: 001-412-624-9163
Home-page: http://www.phyast.pitt.edu/~micheles/




More information about the Python-list mailing list