Default attribute values pattern

George Sakkis george.sakkis at gmail.com
Sat Jan 19 13:14:17 EST 2008


A situation that often comes up is having to initialize several
instance attributes that accept a default value. For a single class,
passing the default values in __init__ is fine:

    class Base(object):
        def __init__(self, x=0, y=None):
            self.x = x
            self.y = y

For inherited classes that need to override __init__ while keeping a
compatible interface though, the default values have to be repeated:

    class Derived(Base):
        def __init__(self, x=0, y=None, z=''):
            super(Derived,self).__init__(self,x,y)
            self.z = ''

For just two attributes and two classes that's maybe not too bad but
for many attributes and/or derived classes that may span multiple
modules, that doesn't seem to scale from a maintenance point of view,
especially if the defaults change over time.

A pattern I've been using lately instead is store the defaults in
class attributes and let __init__ accept keyword arguments:

    class Base(object):

        x = 0
        y = None

        def __init__(self, **kwds):
            setattrs(self, kwds)

where setattrs is:

    def setattrs(self, attrvals, strict=True):
        if strict:
            # raise AttributeError if some attr doesn't exist already
            for attr in attrvals.iterkeys():
                getattr(self,attr)
        for attr,val in attrvals.iteritems():
            setattr(self, attr, val)

This way, only the new and overriden default attributes have to
repeated in derived classes:

    class Derived(Base):

        x = 1
        z = ''

        def __init__(self, **kwds):
            super(Derived,self).__init__(**kwds)
            print 'In Derived.__init__'


Is this a good way of doing it ? Is there a better pattern ?

George



More information about the Python-list mailing list