In Learning Python 3rd, I saw this code
class wrapper:
def __init__(self, object):
self.wrapped = object
def __getattr__(self, attrname):
print("Trace:", attrname)
return getattr(self.wrapped, attrname)
x = wrapper([1,2,3])
x.append(4)
print(x.wrapped)
I want to know exactly what happens after calling this __getattr__
method, which only returns the method by getattr
.
Why is the result of the last line [1, 2, 3, 4]
?
There is no code that execute the returned function with the original argument.
The wrapper
class does not have a .append
attribute, so Python falls back to the wrapper.__getattr__
method. From the object.__getattr__
special method documentation:
Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for
self
).
The wrapped object (the list object with [1, 2, 3]
) does have a append
attribute (a method), so getattr(self.wrapped, 'append')
returns it.
The returned method is called, passing in 4
, appending that to the self.wrapped
list object.
You can easily reproduce the steps yourself:
>>> wrapped = [1, 2, 3]
>>> getattr(wrapped, 'append')
<built-in method append of list object at 0x107256560>
>>> getattr(wrapped, 'append')(4)
>>> wrapped
[1, 2, 3, 4]