pythonmethods

Externally provided method not receiving self


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?


Solution

  • 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.)