[Tutor] question about descriptors
Peter Otten
__peter__ at web.de
Wed Nov 11 14:06:20 EST 2015
Albert-Jan Roskam wrote:
>> From: steve at pearwood.info
>> Fortunately, Python has an mechanism for solving this problem:
>> the `__getattr__` method and friends.
>>
>>
>> class ColumnView(object):
>> _data = {'a': [1, 2, 3, 4, 5, 6],
>> 'b': [1, 2, 4, 8, 16, 32],
>> 'c': [1, 10, 100, 1000, 10000, 100000],
>> }
>> def __getattr__(self, name):
>> if name in self._data:
>> return self._data[name][:]
>> else:
>> raise AttributeError
>> def __setattr__(self, name, value):
>> if name in self._data:
>> raise AttributeError('read-only attribute')
>> super(ColumnView, self).__setattr__(name, value)
>> def __delattr__(self, name):
>> if name in self._data:
>> raise AttributeError('read-only attribute')
>> super(ColumnView, self).__delattr__(name)
>
> That also seems very straightforward. Why does "if name in self._data:"
> not cause a recursion? self._data calls __getattr__, which has self._data
> in it, which...etc.
__getattr__() is only invoked as a fallback when the normal attribute lookup
fails:
>>> class A(object):
... def __getattr__(self, name):
... return self.data[name]
...
>>> a = A()
>>> a.data = dict(foo="bar")
>>> a.foo
'bar'
>>> del a.data
>>> import sys
>>> sys.setrecursionlimit(10)
>>> a.foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __getattr__
File "<stdin>", line 3, in __getattr__
File "<stdin>", line 3, in __getattr__
RuntimeError: maximum recursion depth exceeded while calling a Python object
If you need to intercept every attribute lookup use __getattribute__():
>>> class B(A):
... def __getattribute__(self, name):
... print "looking for", name
... return super(B, self).__getattribute__(name)
...
>>> b = B()
>>> b.data = dict(foo="bar")
>>> b.foo
looking for foo
looking for data
'bar'
More information about the Tutor
mailing list