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