[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