Welcome, guest | Sign In | My Account | Store | Cart

This class wraps any object, and allows accessing and modifying that object's properties using the dict interface. This wrapper is meant to provide a clean interface to getattr/setattr/hasattr/delattr.

Python, 84 lines
 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
78
79
80
81
82
83
84
class attrview(object):
    """Wrapper class that provides a dictionary-style, dynamic access to
    the properties of the wrapped object.  Any mutating map operations
    done to the wrapper mutate the wrapped object.

    Because objects may implement attributes using __getattr__ and
    friends, and there is no __dir__ method for objects to specify
    these attributes, it is not possible to enumerate the attributes
    of an object in general.  attrview does not implement the parts of
    the dictionary interface that assume the set of keys is
    deterministic.  Notably, __iter__, keys, values, and items are
    unimplemented.

    """
    def __init__(self, obj):
        """Return an attrview wrapper which provides dictionary-style, dynamic
        access to the properties of the wrapped object.

        """
        self.__wrapped = obj

    def __contains__(self, prop):
        """Return true if the wrapped object has property prop, else False.

        """
        return hasattr(self.__wrapped, prop)

    def __delitem__(self, prop):
        """Delete the property prop from the wrapped object."""
        if not hasattr(self.__wrapped, prop):
            raise KeyError(prop)
        delattr(self.__wrapped, prop)

    def __getitem__(self, prop):
        """Return the value of property prop on the wrapped object."""
        if not hasattr(self.__wrapped, prop):
            raise KeyError(prop)
        return getattr(self.__wrapped, prop)

    def __setitem__(self, prop, val):
        """Set the value of property prop on the wrapped object to val."""
        setattr(self.__wrapped, prop, val)

    def get(self, prop, default=None):
        """Return the value of property prop on the wrapped object if present,
        else default.

        """
        return getattr(self.__wrapped, prop, default)

    def has_key(self, prop):
        """Return true if the wrapped object has property prop, else False.

        """
        return hasattr(self.__wrapped, prop)

    def setdefault(self, prop, val=None):
        """Return self.get(prop, val).  Also set the property prop on the
        wrapped object to val if it currently does not exist.

        """
        if hasattr(self.__wrapped, prop):
            return getattr(self.__wrapped, prop)
        else:
            setattr(self.__wrapped, prop, val)
            return val

    def update(self, d, **kw):
        """Update the properties of the wrapped object from d and kw, with the
        same semantics as dict.update.

        if d has keys, for k in d: self[k] = d[k]
        else, for k, v in d: self[k] = v
        then, for k in kw: self[k] = kw[k].

        """
        if hasattr(d, 'keys'):
            for k in d:
                self[k] = d[k]
        else:
            for k, v in d:
                self[k] = v
        for k, v in kw.iteritems():
            self[k] = v

In python-dev, during discussion of PEP 363, Calvin Spealman noted that it would be useful to have a wrapper class that provides dictionary-like access to attributes.

Here is my take on the idea. I believe the resulting class is more elegant than get/set/has/delattr, and can express clearly things the original syntax cannot, like attrview(obj)[prop] += 3 or attrview(obj).setdefault(prop, []).append(x)

Though this was suggested as an alternative to a proposed syntax change, I think providing mapping-style access to object properties is generally useful.

As noted in the docstrings, this class does not implement the full mapping interface. Notably, since the set of attributes an object has cannot be reliably determined, attrview objects are not iterable.

Created by Greg Falcon on Thu, 15 Feb 2007 (PSF)
Python recipes (4591)
Greg Falcon's recipes (1)

Required Modules

  • (none specified)

Other Information and Tasks