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 = yor 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
