automatic accessors to a member var dict elements?

Bengt Richter bokr at oz.net
Fri Oct 15 18:34:35 CEST 2004


On 15 Oct 2004 08:30:02 GMT, Nick Craig-Wood <nick at craig-wood.com> wrote:

>Jeff Shannon <jeff at ccvcorp.com> wrote:
>>      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 
>>  rules. 
>
>It doesn't!
Oops, I missed that too, as I was focusing on the if-value-is-None logic,
>
>>>> 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

Maybe:

 >>> class MyClass(object):        # ensure a new-style class
 ...     def __init__(self):
 ...         object.__setattr__(self, 'm_dict', {'one':1, 'two':2, 'three':3})
 ...     def __getattr__(self, attr):
 ...         if attr == 'm_dict': return object.__getattribute__(self, attr)
 ...         try: return self.m_dict[attr]
 ...         except KeyError: raise AttributeError(attr)
 ...     def __setattr__(self, attr, value):
 ...         self.m_dict[attr] = value
 ...
 >>> mc = MyClass()
 >>> mc.two
 2
 >>> mc.three
 3
 >>> mc.four
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 7, in __getattr__
 AttributeError: four
 >>> mc.four = 4
 >>> mc.four
 4
 >>> mc.m_dict
 {'four': 4, 'three': 3, 'two': 2, 'one': 1}

>... 
>>>> obj = MyClass()
>Traceback (most recent call last):
>  File "<stdin>", line 1, in ?
>  File "<stdin>", line 3, in __init__
>  File "<stdin>", line 10, in __setattr__
>  File "<stdin>", line 5, in __getattr__
>  File "<stdin>", line 5, in __getattr__
>  File "<stdin>", line 5, in __getattr__
>  File "<stdin>", line 5, in __getattr__
>  File "<stdin>", line 5, in __getattr__
>[snip]
>  File "<stdin>", line 5, in __getattr__
>  File "<stdin>", line 5, in __getattr__
>RuntimeError: maximum recursion depth exceeded
>
>I know there is something different about new style classes in this
>area, but thats not it!
>
You can make self.m_dict raise an attribute error too, but then you can't
write your methods with self.m_dict, since that will trigger recursion.
object.__getattribute__(self, 'm_dict') instead.

Bottom line, though: Why use self.m_dict when you get self.__dict__ for free,
along with attribute access? I.e., self.x is effectively self.__dict__['x']

IOW, self.__dict__ works like you went to all that trouble to make self.m_dict work,
unless your class defines class variables or properties that you want to shadow under
all circumstances.



Regards,
Bengt Richter



More information about the Python-list mailing list