__getattr__ is a very nice and powerful method that must be handled with care, otherwise you can discover that it has more power than you expected...
1 2 3 4 5 6 7 8 9 | class SuperClass:
def supermethod(self):
return 'Output of "SuperClass.supermethod(self)".'
class SubClass(SuperClass):
def __getattr__(self, name):
if name == 'special':
return 'Value of attribute "special".'
else: raise AttributeError, name # <<< DON'T FORGET THIS LINE !!
|
If you forget the last line of __getattr__ above, __getattr__ implicitly returns "None" for every attribute name other than "special" and that includes the (otherwise inherited) "supermethod" attribute, so you finish with an unexpected overload of "supermethod"!
Tags: oop
__getattr__ only comes into play after looking in superclasses. When trying to get attribute/method of an object, the object's superclasses are looked up before the __getattr__:
This will print 'super special'.
(But it IS correct that the value returned by __getattr__ is 'None' if no other is given!) willem broekema
Please Fix. William is right... this recepie is incorrect, and should be fixed (or removed). I'd prefer a fix. (If this were a wiki, I'd just MAKE the fix, but there's no mechanism for that in the cookbook. Yet.)
-- Michael Chermside
another problem: loosing callability. There's another problem if you forget the else-branch: your objects loose callability.
The "NoneType" is not callable is because it is trying to look up "__repr__" in order to display it to you, and so it gets back a None from __getattr__ and promptly tries to call it (because it assumes it's a __repr__). You can see this by adding "print 'getting', attr" to your __getattr__()s
I ran into this very problem which is what led me here. Adding the exception line as in the recepie solved my problem; I believe python checks for AttributeErrors and keeps falling back until it can't fall back anymore.
__repr__ is a special case; it should be one of the only (the only?) one that will trigger the strange "NoneType is not callable" error because, if I understand correctly, it's only when you type in an object at the interactive prompt that the follow pattern is run: try: print getattr(object, '__repr__')() except AttributeError: print generic_repr(object) In all other cases it will happily return None to you which would instantly signal to you "oops"
The example given by Martin Schmettow only fails in the Python interactive interpreter for the reasons given by dum dee. Placing the code in a file and executing it works the same with or without an
else
clause.Note that what Mr. Schmettow describes as "callability" is actually just a reference. If the code were to call the instance it created, it would need to use
test()
, with parentheses.