I’ve learned (and remembered) a lot in the past two months as I’ve
gotten back to coding as my primary job. One thing that I guess I never
quite internalized before is how
super works. I have been bitten by
code that looks something like the following a few times in the past month:
class A(object):
def init(self):
super(self.__class__, self).init()
class B(A):
def init(self):
super(B, self).init()
The surprise comes when I try to use my sub-class,
B. Instantiating
B() blows up the stack with:
RuntimeError: maximum recursion depth exceeded while calling a Python object.
What?
According to the
Python 2.7.2 standard library
documentation,
super “return[s] a proxy object that delegates method calls to a
parent or sibling class of type.” So in the case of single inheritance,
it delegates access to the super class, it does not return an instance
of the super class. In the example above, this means that when you
instantiate B, the follow happens:
- enter B.__init__()
- call super on B and call __init__ on the proxy object
- enter A.__init__()
- call super on self.__class__ and call __init__ on the
proxy object
The problem is that when we get to step four,
self still refers to
our instance of
B, so calling
super points back to
A again.
In technical terms: Ka-bloom.
TL;DR: super(self.__class__, self) may look like a neat trick,
but it’s the end of the line for sub-classing.
Further reading: Raymond Hettinger’s excellent
blog post on
super
provides a great overview of
super and shows off the improved Python
3 syntax, which removes the need to write the class name as part of the
super statement. I was really pleased to find the Python standard
library documentation links directly to it.
date: |
2011-07-04 20:44:23 |
wordpress_id: |
1990 |
layout: |
post |
slug: |
super-self |
comments: |
|
category: |
development, python |
tags: |
python, super |