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)
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to