7

Simmilar question (related with Python2: Python: check if method is static)

Lets concider following class definition:

class A:
  def f(self):
    return 'this is f'

  @staticmethod
  def g():
    return 'this is g'

In Python 3 there is no instancemethod anymore, everything is function, so the answer related to Python 2 will not work anymore.

As I told, everything is function, so we can call A.f(0), but of course we cannot call A.f() (argument missmatch). But if we make an instance a=A() and we call a.f() Python passes to the function A.f the self as first argument. Calling a.g() prevents from sending it or captures the self - so there have to be a way to test if this is staticmethod or not.

So can we check in Python3 if a method was declared as static or not?

2
  • Can I ask why you're trying to do this? Commented Jan 7, 2013 at 0:08
  • 1
    of course, I'm making my own plugin framework and I want to inspect some interface declarations and I would love to know if something was declared as staticmethod or not :) Commented Jan 7, 2013 at 0:10

3 Answers 3

10
class A:
  def f(self):
    return 'this is f'

  @staticmethod
  def g():
    return 'this is g'
print(type(A.__dict__['g']))
print(type(A.g))

<class 'staticmethod'>
<class 'function'>
Sign up to request clarification or add additional context in comments.

2 Comments

great! Could you please explain also why A.__dict__['g'] gives something else than A.g?
A.__dict__['g'] is different from A.g because functions are descriptors. Function objects are descriptors because they define a __get__ method, which is invoked by magic when the object is accessed using dot notation (like A.f). The descriptor protocol is how (for example) a function gets transformed into a bound method when called on an instance. Going through the __dict__, rather than using dot notation, bypasses the descriptor protocol.
6

For Python 3.2 or newer, use inspect.getattr_static() to retrieve the attribute without invoking the descriptor protocol:

Retrieve attributes without triggering dynamic lookup via the descriptor protocol, __getattr__() or __getattribute__().

Use isinstance(..., staticmethod) on the result:

>>> from inspect import getattr_static
>>> isinstance(getattr_static(A, 'g'), staticmethod)
True

The function can handle both instances and classes, and will scan the full class hierarchy for you:

>>> class B(A): pass
...
>>> isinstance(getattr_static(B, 'g'), staticmethod)  # inherited
True
>>> isinstance(getattr_static(B(), 'g'), staticmethod)  # instance, inherited
True

Comments

4

I needed this solution and wrote the following based on the answer from @root

def is_method_static(cls, method_name):
    # http://stackoverflow.com/questions/14187973/python3-check-if-method-is-static
    for c in cls.mro():
        if method_name in c.__dict__:
            return isinstance(c.__dict__[method_name], staticmethod)
    raise RuntimeError("Unable to find %s in %s" % (method_name, cls.__name__))

2 Comments

This will only work for static methods that aren't inherited. You can use inspect.getattr_static instead of directly accessing __dict__ if you want to support inherited static methods.
Thanks, getattr_static is new in 3.2. My code runs in both Python2 and Python3

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.