automatic accessors to a member var dict elements?

Alex Martelli aleaxit at yahoo.com
Sat Oct 16 06:17:31 EDT 2004


Jeff Shannon <jeff at ccvcorp.com> wrote:
   ...
> __getattr__() and __setattr__() to redirect accesses of nonexistent 
> attributes into operations on your contained dict, something like this
> (untested):
> 
>     class MyClass(object):        # ensure a new-style class
>         def __init__(self):
>             self.m_dict = {'one':1, 'two':2, 'three':3}
>         def __getattr__(self, attr):
>             value = self.m_dict.get(attr, None)
>             if value is None:
>                 raise AttributeError(attr)
>             return value
>         def __setattr__(self, attr, value):
>             self.m_dict[attr] = value
> 
> I'm using a new-style class to take advantage of improvements in 
> attribute lookup.  For this class, __getattr__()/__setattr__() will only
> be called if attr isn't found through the normal attribute resolution

Yes for __getattr__, but no for __setattr__ -- in both cases, just like
in classic classes.  When in __init__ you try to set attr m_dict (and in
this case it wouldn't even make much sense to say it's "found through
the normal attribute resolution" -- it's not there yet at that time, so
it couldn't be found), this invokes __setattr__, which goes boom
(because m_dict ain't set yet).  If you needed that __setattr__, your
__init__ should assign self.__dict__['m_dict'] instead.  But the OP
didn't ask for that __setattr__ anyway, so I'd remove it instead.

> rules. 
> 
> One problem with the way I'm doing things here is that, if you set a 
> dict item to a value of None, the object will raise an AttributeError
> when trying to access that item.  This really ought to use a safer 
> sentinel value.  (Check for a recent thread here in c.l.py about 
> sentinel values and the use of object() as one.)

A better solution than a sentinel, in this case:

    def __getattr__(self, attr):
        try: return self.m_dict[attr]
        except KeyError: raise AttributeError, attr

 
> It might be possible to use the mechanism you seem to want 
> (automatically generating individual get/set methods, attaching them to
> the instance, creating a new property from the getter/setter), but that
> would involve significantly more complexity and magic, and would gain
> you very little (if anything).

Complete agreement here -- __getattr__ is clearly the way to go for this
specific requirement.


Alex



More information about the Python-list mailing list