class.__getattr__ behavior: feature or bug?

Tim Peters tim_one at email.msn.com
Fri Jan 14 18:22:57 EST 2000


[Huayin Wang]
> I used to think that I know what's a bug and what's a
> feature, now I am confused.

Well, you're playing with low-level hooks now!  They're both powerful and
dangerous.  *Expect* to spend a lot of time debugging when you work at this
level; and stay away from this level unless you truly need this kind of
power.

> I do not understand why I would want to use __getattr__
> special method to control/define other special methods
> like '__repr__' when I can just define it if I want to.

__getattr__/__setattr__ make no distinction between "special" methods and
"other" methods -- they wouldn't be powerful enough to do their jobs if they
didn't apply to *all* methods.  By defining __getattr__, you're telling
Python "I don't like the way *you* look up attributes, so I'm going to do it
myself".  In return for the power, you also have to take full responsibility
for doing everything Python does for you when you don't use __getattr__.

BTW, part of what Python normally does for you is raise AttributeError  when
it can't find an attribute.  As another followup said, if your __getattr__
had raised AttributeError instead of returning None when looking up
__repr__, your program would have worked (well, it would have run a little
longer <wink>).

> By the way, does any of you tested you code/idea ;) and
> is infinite __getattr__ loop a bug?

>> your-next-post-will-be-wondering-whether-an-infinite-
>>    __getattr__-loop-is-a-bug<0.5-wink>-ly y'rs  - tim

> never mind :)

Heh heh.  If a __getattr__ hook is defined, you have to be very sure that
self.x is defined before __getattr__ is called, for every x such that the
__getattr__ implementation references self.x (else __getattr__ will invoke
itself again, ad infinitum).  That's a mouthful too, but it's obvious after
the first six times you debug it <wink>.

__setattr__ is even subtler, because it's called even for attributes that
*are* already defined.  This is why you'll sometimes see bizarre code like

    self.__dict__[somename] = somevalue

in methods of classes that define __setattr__; it's a way of spelling

    setattr(self, somename, somevalue)

that *doesn't* trigger __setattr__.

the-surest-way-to-avoid-these-surprises-is-to-avoid-
    these-methods-ly y'rs  - tim






More information about the Python-list mailing list