In article <[EMAIL PROTECTED]>, "Enrico" <[EMAIL PROTECTED]> wrote:
> Hi there, > I have the following situation (I tryed to minimize the code to concentrate > on the issue): > > >>> class A(object): > def __getattr__(self, name): > print 'A.__getattr__' > if name == 'a': return 1 > raise AttributeError('%s not found in A' % name) > > >>> class B(object): > def __getattr__(self, name): > print 'B.__getattr__' > if name == 'b': return 1 > raise AttributeError('%s not found in B' % name) > > Both classes have a __getattr__ method. > Now I want to have a class that inherits from both so I write: > > >>> class C(B,A): > pass > > The problem arise when I try something like this: > >>> c=C() > >>> c.a > A.__getattr__ > 1 > >>> c.b > A.__getattr__ > > Traceback (most recent call last): > File "<pyshell#47>", line 1, in <module> > c.b > File "<pyshell#42>", line 5, in __getattr__ > raise AttributeError('%s not found in A' % name) > AttributeError: b not found in A > > I was expecting, after a fail in A.__getattr__, a call to the __getattr__ > method of B but it seems that after A.__getattr__ fails the exception stops > the flow. So, if I did understand well, B.__getattr__ will be never called > "automatically". I don't know if this has a reason, if it is a design choice > or what else, any explanation is welcome. Well, it's simply the way it works. When you say C(A, B) then A is searched first for a given attribute and if A has no such attribute then B is searched. If you really want to do something like this then yes, you have to do something as below. I suspect that the people who feel expert enough to talk about what you should and shouldn't want are going to say that you shouldn't want something like this - with things set up the way you have them you really can't tell what's going to happen with c.__getattr__ unless you look at all the code in all the subclasses. > Since A and B are not written by me I can only work on C. The solution that > comes to my mind is to define a __getattr__ also in C and write something > like: > > >>> class C(A,B): > def __getattr__(self, name): > try: > return A.__getattr__(self, name) > except AttributeError: > return B.__getattr__(self, name) > > >>> c=C() > >>> c.a > A.__getattr__ > 1 > >>> c.b > A.__getattr__ > B.__getattr__ > 1 > > A better solution is welcome. > Many thanks, Enrico -- David C. Ullrich -- http://mail.python.org/mailman/listinfo/python-list