[Patches] [ python-Patches-1094542 ] add Bunch type to collections module

SourceForge.net noreply at sourceforge.net
Tue Jan 25 21:06:30 CET 2005


Patches item #1094542, was opened at 2005-01-02 11:26
Message generated for change (Comment added) made by bediviere
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=305470&aid=1094542&group_id=5470

Category: None
Group: Python 2.5
Status: Open
Resolution: None
Priority: 5
Submitted By: Steven Bethard (bediviere)
Assigned to: Nobody/Anonymous (nobody)
Summary: add Bunch type to collections module

Initial Comment:
This patch adds a proposed Bunch type to the
collections module which complements Python's dict
type, which provides a name-value mapping through the
__getitem__ protocol, with the Bunch type, which
provides an attribute-value mapping through
dotted-attribute access.

Example:
>>> x = Bunch(spam=Bunch(rabbit=1, badger=[2, 3, 4]),
ham='neewom')
>>> x.spam.badger
[2, 3, 4]
>>> x.ham
'neewom'



----------------------------------------------------------------------

>Comment By: Steven Bethard (bediviere)
Date: 2005-01-25 13:06

Message:
Logged In: YES 
user_id=945502

Ok, I'll post the current PEP draft below.  Of course, I
welcome any suggestions to make its acceptance more likely.
 I'll definitely update the __eq__ docstring as suggested,
but I'll probably wait until I've heard what other changes
should be made.

----------------------------------------------------------------------
PEP: XXX
Title: Generic Object Data Type
Version: $Revision: 1.0 $
Last-Modified: $Date: 2004/11/29 16:00:00 $
Author: Steven Bethard <steven.bethard at gmail.com>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 29-Nov-2004
Python-Version: 2.5
Post-History: 29-Nov-2004


Abstract
========

This PEP proposes a standard library addition to support the
simple
creation of 'generic' objects which can be given named
attributes
without the need to declare a class. Such attribute-value
mappings are
intended to complement the name-value mappings provided by
Python's
builtin dict objects.


Motivation
==========

Python's dict objects provide a simple way of creating anonymous
name-value mappings. These mappings use the __getitem__
protocol to
access the value associated with a name, so that code
generally appears
like::

    mapping['name']

Occasionally, a programmer may decide that dotted-attribute
style access
is more appropriate to the domain than __getitem__ style
access, and
that their mapping should be accessed like::

    mapping.name

Currently, if a Python programmer makes this design
decision, they are
forced to declare a new class, and then build instances of
this class.
When no methods are to be associated with the
attribute-value mappings,
declaring a new class can be overkill.  This PEP proposes
adding a
simple type to the collections module of the standard
library that can
be used to build such attribute-value mappings.

Providing such a type allows the Python programmer to
determine which
type of mapping is most appropriate to their domain and
apply this
choice with minimal effort.  Some of the suggested uses include:


Returning Named Results
-----------------------

It is often appropriate for a function that returns multiple
items to
give names to the different items returned.  The type
suggested in this
PEP provides a simple means of doing this that allows the
returned
values to be accessed in the usual attribute-style access::

    >>> def f(x):
    ...     return Bunch(double=2*x, squared=x**2)
    ... 
    >>> y = f(10)
    >>> y.double
    20
    >>> y.squared
    100


Representing Hierarchical Data
------------------------------

The type suggested in this PEP also allows a simple means of
representing hierarchical data that allows attribute-style
access::

    >>> x = Bunch(spam=Bunch(rabbit=1, badger=[2, 3, 4]),
ham='neewom')
    >>> x.spam.badger
    [2, 3, 4]
    >>> x.ham
    'neewom'


Rationale
=========

As Bunch objects are intended primarily to replace simple,
data-only
classes, simple Bunch construction was a primary concern. 
As such,
the Bunch constructor supports creation from keyword
arguments, dicts,
and sequences of (attribute, value) pairs::

    >>> 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)

To allow attribute-value mappings to be easily combined, the
update
method of Bunch objects supports similar arguments.

If Bunch objects are used to represent hierarchical data,
comparison of
such objects becomes a concern.  For this reason, Bunch
objects support
object equality::

    >>> x = Bunch(parrot=Bunch(lumberjack=True, spam=42),
peng='shrub')
    >>> y = Bunch(peng='shrub', parrot=Bunch(spam=42,
lumberjack=True))
    >>> z = Bunch(parrot=Bunch(lumberjack=True), peng='shrub')
    >>> x == y
    True
    >>> x == z
    False


Note that support for the various mapping methods, e.g.
__(get|set|del)item__, __len__, __iter__, __contains__,
items, keys,
values, etc. was intentionally omitted as these methods did
not seem to
be necessary for the core uses of an attribute-value
mapping.  If such
methods are truly necessary for a given use case, this may
suggest that
a dict object is a more appropriate type for that use.


Examples
=========

Converting an XML DOM tree into a tree of nested Bunch objects::

    >>> import xml.dom.minidom
    >>> def getbunch(element):
    ...     result = Bunch()
    ...     if element.attributes:
    ...         result.update(element.attributes.items())
    ...     children = {}
    ...     for child in element.childNodes:
    ...         if child.nodeType ==
xml.dom.minidom.Node.TEXT_NODE:
    ...             children.setdefault('text', []).append(
    ...                 child.nodeValue)
    ...         else:
    ...             children.setdefault(child.nodeName,
[]).append(
    ...                 getbunch(child))
    ...     result.update(children)
    ...     return result
    ... 
    >>> doc = xml.dom.minidom.parseString("""    ... <xml>
    ...   <a attr_a="1">
    ...     a text 1
    ...     <b attr_b="2" />
    ...     <b attr_b="3"> b text </b>
    ...     a text 2
    ...   </a>
    ...   <c attr_c="4"> c text </c>
    ... </xml>""")
    >>> b = getbunch(doc.documentElement)
    >>> b.a[0].b[1]
    Bunch(attr_b=u'3', text=[u' b text '])


Reference Implementation
========================

The code is available as SourceForge patch 1094542 [1]_.


Open Issues
===========
What should the type be named?  Some suggestions include
'Bunch',
'Record', 'Struct' and 'Namespace'.

Where should the type be placed?  The current suggestion is the
collections module.


References
==========

.. [1]
http://sourceforge.net/tracker/index.php?func=detail&aid=1094542&group_id=5470&atid=305470


..
   Local Variables:
   mode: indented-text
   indent-tabs-mode: nil
   sentence-end-double-space: t
   fill-column: 70
   End:


----------------------------------------------------------------------

Comment By: Alan Green (alanvgreen)
Date: 2005-01-24 05:34

Message:
Logged In: YES 
user_id=1174944

Some thoughts while we wait for the PEP:

1. This doesn't look like a collection class to me. It's
more of a  convenient substitute for a first-class object.
The PEP would need to include a rationale as to why this
class is in the collections module.

2. It may be desireable to make the core parts of  Bunch
(equality test, repr, and update) available as functions
that other classes can use if appropriate. This might help
developers building objects more complex than a Bunch. Then
again, maybe not, but I'd like to see the PEP address this.

3. The docstring on __eq__ should explicitly say what
consitutes equality for bunches: both bunches have the same
attributes and the same values for those attributes.

4. It's easy enough to convert a dict to a Bunch (via the
Bunch constructor), but I would have expected that there be
a way to convert a Bunch to a dict. 

Overall, a useful concept, but I'd like to read the PEP -
you could always upload your draft to this patch item :)



----------------------------------------------------------------------

Comment By: Steven Bethard (bediviere)
Date: 2005-01-10 08:15

Message:
Logged In: YES 
user_id=945502

I submitted a PEP for it on 2 Jan 2005, but I haven't heard
back from peps at python.org yet.  Sorry, I didn't realize it
might take so long to get a PEP number.

----------------------------------------------------------------------

Comment By: Michael Chermside (mcherm)
Date: 2005-01-10 07:08

Message:
Logged In: YES 
user_id=99874

Would someone be willing to provide the motivation for
adding this class? I'm certainly willing to listen, but I'm
not convinced this is worth adding to the std library. (I
guess that's a -0 vote.)

----------------------------------------------------------------------

Comment By: Reinhold Birkenfeld (birkenfeld)
Date: 2005-01-03 10:38

Message:
Logged In: YES 
user_id=1188172

Let me add that the main functionality consists in the easy
initializing and updating (otherwise, you just could use an
empty class).

I'm +1 on the class, but I would call it `bunch'.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=305470&aid=1094542&group_id=5470


More information about the Patches mailing list