[CentralOH] A simple class to provide named fields
William McVey
wam at cisco.com
Wed Jan 16 23:57:26 CET 2008
On Wed, 2008-01-16 at 16:28 -0500, Brandon Mintern wrote:
> Some time ago, I came up with an elegant solution to this problem, one
> that I thought I would share. If anyone else has used or seen
> something like this, I would love to hear about it.
I have something similar:
class Container(object):
"""A generic object that initializes its attributes from the init params
If a subclass defines a 'params' iterable at the class definition level,
only those parameters will be assigned and extra keyword arguments will
raise a NameError. Failure to provide a field specified by the
subclass' params list will result in None being assigned that value
"""
params = []
def __init__(self, *args, **kwargs):
if not self.params:
self.__dict__.update(kwargs)
return
for param in self.params:
self.__dict__[param] = kwargs.get(param, None)
try:
del(kwargs[param])
except KeyError:
pass
if kwargs:
raise NameError(
"%s initialized with extra params: %r" % (
self.__class__.__name__, kwargs.keys()))
def __repr__(self):
return "%s(%s)" % (
self.__class__.__name__,
", ".join(["%s=%r" % x for x in self.__dict__.items()]))
It's very similar in concept to yours; however, I tend to prefer classes
which are tied closer to the data object I'm storing, so I almost always
subclass Container. In my subclass I define a class attribute named
'params' which specifies which parameters/fields I accept. I then go
about creating a PersonRecord the same way you create your Fields
objects: For example:
>>> from wam.Utils import Container
>>> class PersonRecord(Container):
... params = ["fname", "lname", "status"]
...
>>> me = PersonRecord(fname="William", lname="McVey", status="Active")
>>> me
PersonRecord(lname='McVey', status='Active', fname='William')
>>> me.status
'Active'
The nice thing is that if I try and send down an unexpected field value
(a sure sign of a bug), I get myself a traceback that indicates what the
problem is. In the rare cases where I just want a generic
"accept-anything" object, I just don't define the fields the object
should be constrained by.
I also really like having __repr__ methods that can recreate the object
in question.
-- William
P.S. Note the use of the update() method on the dictionary. That would
shorten your version to a one liner:
def __init__(self, **kwargs): self.__dict__.update(kwargs)
More information about the CentralOH
mailing list