While methods are usually defined inside the class block with def func(self, ...):, this is not required:
def method(self):
return self.x
class Foo:
def __init__(self, x):
self.x = x
func = method
foo = Foo(5)
foo.func() # 5
Also,
class Foo:
func = lambda x: print(x)
foo = Foo()
foo.func() # <__main__.Foo object at 0xdeadbeef>
However, when I do
class Foo:
func = print
foo = Foo()
foo.func()
an empty line is printed. I thought that self would be passed and printed. Why is this?
print is not a descriptor like a user-defined function, which is what makes method-call magic happen.
Compare
>>> method.__get__
<method-wrapper '__get__' of function object at 0x10883c7d0>
to
>>> print.__get__
Traceback (most recent call last):
File "<python-input-15>", line 1, in <module>
print.__get__
AttributeError: 'builtin_function_or_method' object has no attribute '__get__'. Did you mean: '__ge__'?
foo.func is equivalent to Foo.__dict__['func'].__get__(foo, Foo) when __get__ is available, otherwise it's just Foo.__dict__['func']. (I'm using __dict__ to indicate ordinary access, rather than the full attribute lookup algorithm.)