Thursday, November 27, 2008

Python: Class Methods Make Good Factories

Alex Martelli explained something to me a while back. One of the best uses of class methods is as constructors. For instance, if you want to have multiple constructors, but don't want to rely on one method that simply accepts different sorts of arguments, then use different class methods. The datetime module does this; it has class methods like fromordinal and fromtimestamp to create new datetime instances.

My first thought was that you could just as well use standalone factory functions. However, he brought up a good point. If I use a factory function, the class name is hard coded in the factory function. It can't easily return an instance of some subclass of the class. That's not the case with class methods.

Let me show you what I mean:
class MyClass:

def __init__(self):
# This is the "base" constructor.

def one_constructor(klass, foo):
# This is one special constructor.
self = klass() = foo
return self

def another_constructor(klass, bar):
# This is another special constructor.
# ...

class MySubclass(MyClass):
# This does some necessary customizations.

obj = MySubclass.one_constructor('foo')
Here I am instantiating an instance of MySubclass, but I am using the class method one_constructor from the superclass as the constructor.

If you've followed me so far, then perhaps you can imagine why Java's "public static void main" sometimes makes sense for Python too.


Jerry Ji said...

-> import pdb; pdb.set_trace()
(Pdb) list
22 # This does some necessary customizations.
23 pass
26 obj = MySubclass.one_constructor('foo')
27 -> import pdb; pdb.set_trace()
(Pdb) obj

obj is None?

David Goodger said...

You forgot to return the objects from the constructors.

Shannon -jj Behrens said...

Sorry about that. Hmm, perhaps I should write doctests for my blog posts ;)

Igor said...

Thanks, simple and to the point.