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