Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing static methods in python

Could you explain why the following code snippet doesn't work?

class A:
    @staticmethod
    def f():
        print('A.f')

    dict = {'f': f}

def callMe(g):
    g()

callMe(A.dict['f'])

It yields

TypeError: 'staticmethod' object is not callable

Interesingly, changing it to

class A:
    @staticmethod
    def f():
        print('A.f')

    dict = {'f': f}

def callMe(g):
    g()

callMe(A.f)

or to

class A:
    @staticmethod
    def f():
        print('A.f')

    dict = {'f': lambda: A.f()}

def callMe(g):
    g()

callMe(A.dict['f'])

gives the expected result

A.f

As far as I see the behaviour is the same in Python 2 and 3.

like image 633
grześ Avatar asked Oct 28 '25 05:10

grześ


1 Answers

The f object inside A is a descriptor, not the static method itself -- it returns the staticmethod when called with an instance of A; read the link, and look up the "descriptor protocol" for more info on how this works. The method itself is stored as the __func__ attribute of the descriptor.

You can see this for yourself:

>>> A.f
<function A.f at 0x7fa8acc7ca60>
>>> A.__dict__['f']
<staticmethod object at 0x7fa8acc990b8>
>>> A.__dict__['f'].__func__ # The stored method
<function A.f at 0x7fa8acc7ca60>
>>> A.__dict__['f'].__get__(A) # This is (kinda) what happens when you run A.f
<function A.f at 0x7fa8acc7ca60>

Also note that you can use A.__dict__ to access the f descriptor object, you don't need to make your own dictionary to store it.

like image 81
tzaman Avatar answered Oct 29 '25 18:10

tzaman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!