When attr == '__str__'
, the function needs to return a callable object, because __str__
is expected to be a method. Simply returning a string will give you an error complaining that 'str' objects aren't callable.
However, the *args
is not needed because __str__
is never called with any arguments. This suffices:
return lambda: '[Getattr str]'
Note that if you use python2 and inherit from object
as is recommended, the example doesn't work. And if you use python3, it doesn't work either. This is the output in those cases:
getattr: __call__
None
<__main__.GetAttr object at 0xb728ff6c>
Why isn't __getattr__
invoked when attr == '__str__'
?
It's because the base class object
already implements a default __str__
method, and our __getattr__
function is only called for missing attributes. To fix the example as it is we must use the __getattribute__
method instead, but beware of the dangers.
class GetAttr(object):
def __getattribute__(self, attr):
print('getattr: ' + attr)
if attr == '__str__':
return lambda: '[Getattr str]'
else:
return lambda *args: None
A better and more readable solution would be to simply override the __str__
method explicitly.
class GetAttr(object):
def __getattr__(self, attr):
print('getattr: ' + attr)
return lambda *args: None
def __str__(self):
return '[Getattr str]'
But though it's better python, much of the point of the example is lost.