Wandering Thoughts archives

2011-08-18

You should always use super()

I've done it (and now I'm embarrassed by that). I've seen other people do it by accident (to pick something I was recently looking at). And yes, I know, using super() is kind of annoying (Python 3 makes it much nicer). But still: you should always use super() instead of directly calling up to your parent class.

(It's mostly a coincidence that both examples I gave here are metaclasses, except that a metaclass is one of the few cases in Python where you have to call up to a built-in type.)

It may not be obvious to people what problems not using super() causes, so I'll give an example in the traditional illustrated form:

class Meta1(type):
  def __new__(meta, name, bases, odict):
    print "meta1 new"
    return type(name, bases, odict)

class Meta2(type):
  def __new__(meta, name, bases, odict):
    print "meta2 new"
    return type(name, bases, odict)

class Joined(Meta1, Meta2):
  pass

class Testing(object):
  __metaclass__ = Joined
  def frotz(self):
    print "frotzing", self

Imagine that you have two metaclasses, each of which does something useful to your class. You want to combine them, getting both effects, so you create the Joined metaclass to multi-inherit from them. But when you try it you discover that despite the multi-inheritance, only one of them is actually taking effect; in this example, you'll only see 'meta1 new' printed when you want to see both that and 'meta2 new'. Consistently using super() avoids this problem and makes sure that all metaclasses get invoked (in what is considered the right order). A similar situation happens any time more than one class is modifying a single method.

(Metaclasses are especially prone to this because they're one of the cases where several classes commonly need to modify the exact same method. Many other cases of multiple inheritance and mixin classes have the additional classes overriding disjoint methods.)

The need for super() is interesting partly because it's one of the few places where a Python class can easily close itself to later outside modification. Python classes are in general famously 'open'; outside people can reach into them to change things, forcefully subclass them, and otherwise do things that the original class might object to (and that other languages allow the original class to prevent). But a class that fails to use super() (whether through neglect or deliberate choice) can't be safely used in a multiple inheritance situation; you can't use it as a mixin or mix other things in with it. And it's not something that is at all easily fixed from outside, since you can't just straightforwardly subclass the class and replace the particular errant method.

(If you have a single non-super()-using class, you can sometimes manage to manipulate the method resolution order so that the 'bad' class is the last class and so things work. Among other things, this is quite fragile.)

python/AlwaysUseSuper written at 00:54:32; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.