Albert-Jan Roskam wrote: >> From: st...@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' _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor