views:

176

answers:

2

In python 2.x, super accepts the following cases

class super(object)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 |  Typical use to call a cooperative superclass method:

as far as I see, super is a class, wrapping the type and (eventually) the instance to resolve the superclass of a class.

I'm rather puzzled by a couple of things:

  • why there is also no super(instance), with typical usage e.g. super(self).__init__(). Technically, you can obtain the type of an object from the object itself, so the current strategy super(ClassType, self).__init__() is kind of redundant. I assume compatibility issues with old-style classes, or multiple inheritance, but I'd like to hear your point.
  • why, on the other hand, python 3 will accept (see http://stackoverflow.com/questions/576169/python-super) super().__init__() ? I see kind of magic in this, violating the explicit is better than implicit Zen. I would have seen more appropriate self.super().__init__().
+3  A: 

I can't provide a specific answer, but have you read the PEP's around the super keyword? I did a quick google search and it came up with PEP 367 and PEP 3135.

http://www.python.org/dev/peps/pep-0367/

http://www.python.org/dev/peps/pep-3135/#numbering-note

Unlike any other language I know of, most of the time you can find the answers to Python's quirks in the PEP's along with clear rational and position statements.

Update:

Having read through 3135, related emails in the Python Mailing and the language reference it kind of makes sense why it is the way it is for Python 2 vs Python 3.

http://docs.python.org/library/functions.html?highlight=super#super

I think super was implemented to be explicit/redundant just to be on the safe side and keep the logic involved as simple as possible ( no sugar or deep logic to find the parent ). Since super is a builtin function, it has to infer the correct return from what is provided without adding more complication to how Python objects are structured.

PEP 3135 changes everything because it presented and won an argument for a DRY'er approach to super.

David
I agree, but I am trying to get an answer to the question _while_ at the same time increasing stackoverflow information.
Stefano Borini
@Stefano Immediately after I made my original post I started thinking the same thing.
David
+4  A: 

super(ClassType, self).__init__() is not redundant in a cooperative multiple inheritance scheme -- ClassType is not necessarily the type of self, but the class from which you want to do the cooperative call to __init__.

In the class hierarchy C inherits B inherits A, in C.__init__ you want to call superclass' init from C's perspective, and you call B.__init__; then in B.__init__ you must pass the class type B to super -- since you want to resolve calling superclasses of B (or rather, the next in the mro after B of the class C).

class A (object):
  def __init__(self):
    pass

class B (A):
  def __init__(self):
    super(B, self).__init__()

class C (B):
  def __init__(self):
    super(C, self).__init__()

if you now instantiate c = C(), you see that the class type is not redundant -- super(self).__init__() inside B.__init__ would not really work! What you do is that you manually specify in which class the method calling super is (an this is solved in Python 3's super by a hidden variable pointing to the method's class).

Two links with examples of super and multiple inheritance:

kaizer.se
I guess you meant class B(A): and class C(B):
Stefano Borini
However, you are right. It would never be able to call A.__init__() from B, because in method B.__init__() self would be of type C, whose direct super is B, not A. So B.__init__() would be called again.
Stefano Borini
ah you are right about the typo, thanks! And this gets even more complicated in multiple inheritance schemes, I think I can find a link about that.
kaizer.se