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.
pass

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


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


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


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.

Comments

Jerry Ji said…
-> import pdb; pdb.set_trace()
(Pdb) list
22 # This does some necessary customizations.
23 pass
24
25
26 obj = MySubclass.one_constructor('foo')
27 -> import pdb; pdb.set_trace()
[EOF]
(Pdb) obj
(Pdb)

obj is None?
David Goodger said…
You forgot to return the objects from the constructors.
Sorry about that. Hmm, perhaps I should write doctests for my blog posts ;)
Igor said…
Thanks, simple and to the point.