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.

asked Mar 24, 2017 at 16:05

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.

answered Mar 24, 2017 at 16:14
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.

answered Mar 24, 2017 at 16:14

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.