• spacer
  • Community
  • |
  • Code
  • |
  • Docs
  • |
  • Downloads
  • |
  • more
Welcome, guest | Sign In | My Account | Store | Cart
5

A generic attribute container, with pretty printing and recursion protection

Python, 77 lines
spacer Download
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
def recursion_lock(retval, lock_name = "____recursion_lock"):
    def decorator(func):
        def wrapper(self, *args, **kw):
            if getattr(self, lock_name, False):
                return retval
            setattr(self, lock_name, True)
            try:
                return func(self, *args, **kw)
            finally:
                setattr(self, lock_name, False)
        return wrapper
    return decorator

class Container(object):
    def __init__(self, **kw):
        self.__dict__.update(kw)
    @recursion_lock("<...>")
    def __repr__(self):
        attrs = sorted("%s = %r" % (k, v) for k, v in self.__dict__.iteritems() if not k.startswith("_"))
        return "%s(%s)" % (self.__class__.__name__, ", ".join(attrs))
    @recursion_lock("<...>")
    def __str__(self, nesting = 1):
        attrs = []
        indentation = "    " * nesting
        for k, v in self.__dict__.iteritems():
            if not k.startswith("_"):
                text = [indentation, k, " = "]
                if isinstance(v, Container):
                    text.append(v.__str__(nesting + 1))
                else:
                    text.append(repr(v))
                attrs.append("".join(text))
        attrs.sort()
        attrs.insert(0, self.__class__.__name__ + ":")
        return "\n".join(attrs)

---------
example:
---------

>>> c = Container(a=1, b="baaa")
>>> c # calls repr()
Container(a = 1, b = 'baaa')
>>> print c # calls str()
Container:
    a = 1
    b = 'baaa'
>>> c.c = 1.23
>>> print c
Container:
    a = 1
    b = 'baaa'
    c = 1.23
>>> c.d = Container(e = 6, f = "g")
>>> c
Container(a = 1, b = 'baaa', c = 1.23, d = Container(e = 6, f = 'g'))
>>> print c
Container:
    a = 1
    b = 'baaa'
    c = 1.23
    d = Container:
        e = 6
        f = 'g'
>>> c.h = c # recursive referencing
>>> c
Container(a = 1, b = 'baaa', c = 1.23, d = Container(e = 6, f = 'g'), h = <...>)
>>> print c
Container:
    a = 1
    b = 'baaa'
    c = 1.23
    d = Container:
        e = 6
        f = 'g'
    h = <...>
>>>

similar to the Bunch class that's been on the cookbook since 2001, but better. support pretty representations. very handy as a container for parsed data, etc., where attributes are added dynamically, and you want pretty printing for debugging/demonstrating. it is used extensively in my pyConstruct parsing library.

see also the ExceptionContainer recipe

spacer
Tags: extending

Add a comment

Sign in to comment

spacer Created by tomer filiba on Sat, 13 May 2006 (PSF)
Python recipes (4413)
tomer filiba's recipes (12)

Tags

  • extending
▶ Show machine tags (4) spacer
  • meta:language=python
  • meta:license=psf
  • meta:loc=77
  • meta:score=5

Required Modules

  • (none specified)

Other Information and Tasks

  • Fork this recipe
  • Licensed under the PSF License
  • Viewed 8590 times
  • Revision 1
 
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.