The factory pattern in Python with __new__

Python’s __new__ function allows you to implement the factory pattern in a nice elegant syntax. First, an explanation of __new__.

__new__(klass, *args, **kwargs)

In the normal scheme of things, __new__ is called on a given class in order to create a new instance of that class. __init__ is then called on that object to initialise the new instance. This is all pretty much transparent for most scenarios, where you just override __init__ and accept a blank object (self) as the first argument.

Now, when you override __new__ in a class, the scenario can change slightly. To illustrate, this is the signature of __new__:

class factory(object):
    def __new__(klass, *args, **kwargs):
        ...

__new__ gets called with the type of the object that has been requested as the first argument, and then the rest of the arguments passed in the constructor invocation.

If __new__ returns an instance of klass (which is the usual behaviour), then python goes ahead and runs __init__. It passes the return value of __new__ as the first argument to __init__, followed by the rest of the arguments used in the constructor invocation. For example,

class NormalClass(object):
    def __new__(klass, *args, **kwargs):
        print "__new__ was called on %s" % str(klass)
        return super(NormalClass, klass).__new__(klass, *args, **kwargs)

    def __init__(self):
        print "__init__ was called on : %s" % self

>>> NormalClass()
__new__ was called on <class '__main__.NormalClass'>
__init__ was called on : <__main__.NormalClass object at 0xb76e960c>
<__main__.NormalClass object at 0xb76e960c>

If __new__ returns anything other than an instance of klass, __init__ is not called. This means that you can return a totally different object than the one the piece of calling code requested, without fear that python will try to ‘reinitialise’ it. For example

class ImpossibleClass(object):
    def __new__(klass, *args, **kwargs):
        print "__new__ was called on %s" % str(klass)
        return "Sorry, you can't have one of those"

    def __init__(self):
        print "__init__ was called on : %s" % self

>>> ImpossibleClass()
__new__ was called on <class '__main__.ImpossibleClass'>
"Sorry, you can't have one of those"

Note how __init__ never gets called on ImpossibleClass, since we return an instance of str.

The factory pattern

All this means we can make factory classes that use the normal object creation syntax. For example, say I want a Season factory class that will give me objects representing different seasons. I can override __new__ on the Season class to return instances of Winter, Summer, Spring or Autumn, like so…

class Winter(object):
    pass
class Summer(object):
    pass
class Autmun(object):
    pass
class Spring(object):
    pass

class Season(object):
    seasons = {'winter': Winter, 'summer': Summer, 'autumn': Autumn, 'spring': Spring}

    def __new__(klass, season):
        print "creating a new season %s" % season
        return Season.seasons[season]()

>>> Season('winter')
creating a new season winter
<__main__.Winter object at 0x94ed50c>

The Season class here is acting as a factory for instances of Winter, Summer, Spring and Autumn.

Obviously this is a contrived example, but it shows you how you can use this elegant syntax to implement the factory pattern anywhere you would normally use it.

Comments

Make comment

Required. 30 chars of fewer.

Required.

captcha image Please, enter symbols, which you see on the image