I stumbled across this behaviour, which suggests that you can use getattr
to call methods on a class instance, as an alternative to the intuitively named operator.methodcaller
:
from operator import methodcaller
class Foo():
def __init__(self, lst):
self.lst = lst
def summer(self):
return sum(self.lst)
my_obj = Foo(range(11))
res1 = methodcaller('summer')(my_obj) # 55
res2 = getattr(my_obj, 'summer')() # 55
assert res1 == res2
I'd like to understand, internally, why this works. Is it because all methods are also attributes? This seems to be the case because dir(Foo)
or dir(my_obj)
includes 'summer'
. But I have never heard methods referred to as attributes of a class or class instance, e.g. this isn't mentioned in What is a “method” in Python?
There is an explanation in the docs which mentions differentiation between "data attributes" and "non-data attributes" which I failed to understand.
Update: Comments by @Amadan have clarified most of the above. The only remaining bit I do not understand is this excerpt from the docs:
If you still don’t understand how methods work, a look at the implementation can perhaps clarify matters. When a non-data attribute of an instance is referenced, the instance’s class is searched. If the name denotes a valid class attribute that is a function object, a method object is created by packing (pointers to) the instance object and the function object just found together in an abstract object: this is the method object.
So is a non-data attribute determined by checking whether it is callable, or is there some other way that's used to determine it's a function object? What does "packing pointers" to the instance object mean? What's an abstract object?