Default attribute values pattern
David Tweet
davidtweet at gmail.com
Sat Jan 19 18:02:00 EST 2008
Hello,
Seems to me that setattrs sort of assumes that you want to have all your
initialization arguments set as attributes of the same name. I would think
you'd sometimes want to be able to process the extra arguments inside of each
__init__, assign them to attributes with different names, etc.
My approach would be to treat each __init__ as a wrapping function, grabbing
the items it needs out of the keyword dictionary and then calling the next
__init__. Curious to hear other approaches though:
def Grab(argdict, key, default):
"""Like argdict.get(key, default), but also deletes key from argdict."""
if key in argdict:
retval = argdict["key"]
del(argdict[key])
else:
retval = default
return retval
class Base(object):
def __init__(self, x=0, y=None):
print "in Base init"
self.x = x
self.y = y
class Derived1(Base):
def __init__(self, **kwargs):
print "in Derived1 init"
self.z = Grab(kwargs, "z", None)
super(Derived1, self).__init__(**kwargs)
class Derived2(Derived1):
def __init__(self, **kwargs):
print "in Derived2 init"
self.a = Grab(kwargs, "a", 0)
self.b = Grab(kwargs, "b", False)
super(Derived2, self).__init__(**kwargs)
print self.__dict__
newthing = Derived2(x=234, y="blah", a=55555)
On Jan 19, 2008 10:14 AM, George Sakkis <george.sakkis at gmail.com> wrote:
> 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
> --
> http://mail.python.org/mailman/listinfo/python-list
>
--
-David
More information about the Python-list
mailing list