In Python, does “favor composition over inheritance” – really apply at all?

Googling best practices for classes in Python for a Django project I kept coming across the phrase “favor composition over inheritance” and the Strategy Design Pattern. First let me quote wikipedia on composition over inheritance:

Composition over inheritance in object-oriented programming is a technique by which classes may achieve polymorphic behavior and code reuse by containing other classes which implement the desired functionality instead of through inheritance.[1]

The Strategy Design Pattern is idea is to decouple as much as possible to maximize code use. It looks kinda like this code from S-Lott on  Stack Overflow on Strategy:

class AUsefulThing( object ):
    def __init__( self, aStrategicAlternative ):
        self.howToDoX = aStrategicAlternative
    def doX( self, someArg ):
        self. howToDoX.theAPImethod( someArg, self )

class StrategicAlternative( object ):
    pass

class AlternativeOne( StrategicAlternative ):
    def theAPIMethod( self, someArg, theUsefulThing ):
        pass # an implementation

class AlternativeTwo( StrategicAlternative ):
    def theAPImethod( self, someArg, theUsefulThing ):
        pass # another implementation

Now you can do things like this.

t = AUsefulThing( AlternativeOne() )
t.doX( arg )

S-Lott then provides another Python example pattern that replicates the above with a bit less code.

This had me scratching my head. Not at the example and the helpful response, but at the question itself. Why are we creating functions, then assigning a variable to a class and passing the function in as a parameter? Barooo?

Then on the same stack overflow post there was a follow up response from Christian Groleau as follows:

This pattern is practically non-existent in languages that support first class functions. You may want to consider taking advantage of this feature in Python:

def strategy_add(a, b):
    return a + b

def strategy_minus(a, b):
    return a - b

solver = strategy_add
print solver(1, 2)
solver = strategy_minus
print solver(2, 1)

“This approach is very clean and simple.”

I agree with him. I have made the mistake, granted it was out of desperation, of putting a literal in a public property in a class called “objecttype”. This let me pass the object to a function and make decisions on what to do next. Pseudo vbscript-ish code example:

function generate_invoice(object, d)
    select case(object.objecttype)
        case "jobs"
        #do job invoice stuff
    case "resumes"
        #do resume stuff here
    case else

Ok, so it’s not quite as bad as concatenating a string of vbscript and calling the exec(str) method. But it ain’t pretty either. But both got the job done. And in the case of my fake function above, that sure looks like the composition pattern to me. Maybe not exactly, but it’s close. Functions taking classes as parameters and then calling methods within the class in the name of portability. And to reduce code in the classes themselves of course.

I like Christian’s example above a LOT better. Which makes sense because Python has, as noted by bitwise, both First Class Functions and allows for Meta-programming. “Python is not java without the compile” indeed. First Class Functions and Meta Programming used in combination obviate the need for the Strategy design pattern in Python IMHO (see caveats below). And for further support I found this:

From pycon 2009 – Joe Gregorio – The (lack of) design patterns in Python

“Yes, design patterns are good, but they’re also a sign of weakness in a language.”

The patterns are built in [to Python]. “No one talks about the ‘structured programming’ pattern, or the ‘object-oriented’ pattern, or the ‘function’ pattern anymore.”

………

Conclusions:

  1. look to features before patterns
  2. reduce patterns -> shorter code
  3. needed patterns -> language feature

I’m still a Python newb, but definitely not a programming newb. And So far it looks like you can inherit meta classes with properties to your hearts content to DRY. Yet still, make a thoughtful decision when it comes to how you should implement methods/functions in base classes. Sometimes perhaps a function is better than inheriting a method. Just stop and think. Odds are our fear of inheritance is a learned behavior from being burned by java or another similar lower-level language. I think I need to get over that.

And be thankful that most design patterns are already built into Python. Less code is better.

In closing, and I forget the post I read it on, but just because programming can do ORM (object relational mapping) does NOT mean that a database can. In fact it can’t. And a database deals with the multi-stand-alone class issue by creating a bunch of tables in Django. And one programming matra that I am 100% sure is true is “JOINS are EXPENSIVE.”

Django responds to inherited meta classes by keeping all of the fields in one table, not 20. And perhaps this is me just trying to get over my fear of multi-inheritance and break years of practice. To take advantage of Python being “First Class Everything”. To write code that is  Better, faster, stronger than before.

About eschipul

some guy in houston

14. May 2012 by eschipul
Categories: Programming | 1 comment

One Comment

  1. Very nice post!

    I think the “spirt” in the advice is more about how limiting inheritance is and not about how terrific composition is. When you inherit you fix the relationships rigidly at compile time. But there are other language mechanisms that allow you to compose and recompose the relationships dynamically at runtime, which can be more powerful (and can be more confusing).

    The Strategy pattern is about pointers-to-method-implementations. Python does not “obviate” the need for the Strategy pattern. It does not “obviate” the power you get in wiring up an implementation relationship at runtime – Python simply makes the implementation syntactically easier with pointers-to-method-implementations that are first class citizens. The concept hasn’t changed.