4

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.

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

Comments

1

The staticmethod object is a descriptor, and you need to access it as an attribute (of the class) for the descriptor mechanism to take effect. The staticmethod object itself is not callable, but the result of its __get__ is callable. See also this Python bug discussion.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.