I find myself doing the following very often:
class Struct: pass ... blah = Struct() blah.some_field = x blah.other_field = y ...
Is there a better way to do this?
Yes -- help me rally behind my generic object PEP which proposes a Bunch type (probably to be renamed) for the Python standard lib. =) With this type, you could write your code as:
blah = Bunch() blah.some_field = x blah.other_field = y
or simply:
blah = Bunch(some_field=x, other_field=y)
I requested a PEP number on 2 Jan 2005, but haven't heard back yet. However, you can see a recent draft of the PEP at:
http://mail.python.org/pipermail/python-list/2005-January/262201.html
and you can see the first version of the patch at:
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=1094542&group_id=5470
If you'd like to use the Bunch type now (instead of waiting for a future version of Python, assuming it's accepted), the current code for the Bunch class follows.
STeVe
---------------------------------------------------------------------- # Copyright (c) 2004 Python Software Foundation. # All rights reserved.
# Written by Steven Bethard <steven.bethard at gmail.com>
import operator as _operator
class Bunch(object): """Bunch([bunch|dict|seq], **kwds) -> new bunch with specified attributes
The new Bunch object's attributes are initialized from (if provided) either another Bunch object's attributes, a dictionary, or a sequence of (name, value) pairs, then from the name=value pairs in the keyword argument list.
Example Usage: >>> Bunch(eggs=1, spam=2, ham=3) Bunch(eggs=1, ham=3, spam=2) >>> Bunch({'eggs':1, 'spam':2, 'ham':3}) Bunch(eggs=1, ham=3, spam=2) >>> Bunch([('eggs',1), ('spam',2), ('ham',3)]) Bunch(eggs=1, ham=3, spam=2) >>> Bunch(Bunch(eggs=1, spam=2), ham=3) Bunch(eggs=1, ham=3, spam=2) """
def __init__(*args, **kwds): """Initializes a Bunch instance.""" Bunch.update(*args, **kwds)
def __eq__(self, other): """x.__eq__(y) <==> x == y
Two Bunch objects are considered equal if they have the same attributes and the same values for each of those attributes. """ return (other.__class__ == self.__class__ and self.__dict__ == other.__dict__)
def __repr__(self): """x.__repr__() <==> repr(x)
If all attribute values in this bunch (and any nested bunches) are reproducable with eval(repr(x)), then the Bunch object is also reproducable for eval(repr(x)). """ return '%s(%s)' % (self.__class__.__name__, ', '.join('%s=%r' % (k, v) for k, v in self.__dict__.items()))
@staticmethod def update(*args, **kwargs): """update(bunch, [bunch|dict|seq,] **kwargs) -> None
Updates the first Bunch object's attributes from (if provided) either another Bunch object's attributes, a dictionary, or a sequence of (name, value) pairs, then from the name=value pairs in the keyword argument list. """ if not 1 <= len(args) <= 2: raise TypeError('expected 1 or 2 arguments, got %i' % len(args)) self = args[0] if not isinstance(self, Bunch): raise TypeError('first argument to update should be Bunch, ' 'not %s' % type(self).__name__) if len(args) == 2: other = args[1] if isinstance(other, Bunch): other = other.__dict__ try: self.__dict__.update(other) except (TypeError, ValueError): raise TypeError('cannot update Bunch with %s' % type(other).__name__) self.__dict__.update(kwargs) -- http://mail.python.org/mailman/listinfo/python-list