Thursday, July 2, 2009

Armin Ronacher knows the correct way to use Python's "super"... Do you?

Tweet from "mitsuhiko" (Armin Ronacher) on the mis-uses of Python's "super".

Image of Armin Ronacher from TwitterImage of Armin Ronacher

http://twitter.com/mitsuhiko/status/2438234176 "super" is the built-in function that traverses the Method Resolution Order of bases classes for delegating work inside of a class method. This could be non-trivial, because Python supports multiple inheritance. It is very nice to have a built-in function to do this, but this is the correct way to call "super":
class TypeOutTheClassNameHere(Class1, Class2):

    # methodname - method provided to support delegation

    def methodname(self, x, y, z):
    
        # If you wish for Side-Effects...
        heavy_lifting1(x, y, z)
        
        result = super(TypeOutTheClassNameHere, self).methodname(x, y, z)
        
        return heavy_lifting2(result)
        
# greetings to library users:
# TypeOutTheClassNameHere is ready to be sub-classed!

class OtherClass(TypeOutTheClassNameHere):

    def methodname(self, x, y, z):
    
        heavy_lifting3(x, y, z)
        
        result = super(OtherClass, self).methodname(x, y, z)
        
        return heavy_lifting4(result)
Really Important Point: without unit-testing of the implementation and the success of delegation, using "super" is pure vanity. "super", by itself, cannot magically make your code handle multiple inheritance correctly! Not only do you have to test your class, you have to test that future users of your code, inheriting from your class, will get correct behavior. Yup, your unit-test suite may include creating one-off classes for testing! Armin's tweet demonstrates the prevalence of incorrect use of "super". If you fail to "TypeOutTheClassNameHere", any sub-class to your class will break. http://www.google.com/codesearch?q="super(type(self)"&hl=en&btnG=Search+Code Michele Simionato has a great three-part write-up called "Things to Know About Python Super". ( Part 1, Part 2, Part 3 ) The complexity in any given case is not great, the complexity comes only from considering every single corner case. My view is that unit-testing is a must to make sure the corner cases you are interested in is correctly implemented. Really Important Point: If you have no interest in supporting multiple-inheritance, and you have no interest in supporting sub-classing, don't use "super". It will simply mislead users of your code as a library that you investing in engineering and testing.

Mushroom cloud from the largest nuclear test t...Image via Wikipedia

"super" is an advertisement to the world that you invested in the engineering and testing to support multiple-inheritance and sub-classing! Don't use it if you don't mean it!
I like "super". I only user "super" when I am supporting multiple-inheritance and sub-classing. I write unit-tests whenever I write code with "super". Please take these issues into consideration, for your library code.
Reblog this post [with Zemanta]

No comments: