empty classes as c structs?

Steven Bethard steven.bethard at gmail.com
Fri Feb 4 14:17:24 EST 2005


Christopher J. Bottaro wrote:
> 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)



More information about the Python-list mailing list