1

I executed the following Python code:

class C:
    def m1(self):
        print('method m1')
    def m2(self):
        print('method m2')
    @classmethod
    def m3(cls):
        print('class method')
    @staticmethod
    def m4():
        print('static method')

print()
for key, val in vars(C).items():
    print(key, '***', val, end=' ')
    if callable(val):
        print(True)
    else:
        print(False)

Got the following output:

__module__ *** __main__ False
m1 *** <function C.m1 at 0x7f3661a62dc0> True
m2 *** <function C.m2 at 0x7f3661a735e0> True
m3 *** <classmethod object at 0x7f3661bd4670> False
m4 *** <staticmethod object at 0x7f3661ab4f10> False
__dict__ *** <attribute '__dict__' of 'C' objects> False
__weakref__ *** <attribute '__weakref__' of 'C' objects> False
__doc__ *** None False

I am wondering why callable returns False for @classmethod and @staticmethod.

I am actually trying to find out the names of all methods inside a class so that I can decorate all methods of the class with a user defined decorator

user3282758
  • 1,379
  • 11
  • 29

1 Answers1

1

Use dir(C) and getattr() instead:

class C:
    def m1(self):
        print('method m1')

    def m2(self):
        print('method m2')

    @classmethod
    def m3(cls):
        print('class method')

    @staticmethod
    def m4():
        print('static method')


for val in dir(C):
    if callable(getattr(C, val)):
        print('***', val, end=' ')
        print(True)
    else:
        print(val, False)

Out:

*** __class__ True
*** __delattr__ True
__dict__ False
*** __dir__ True
__doc__ False
*** __eq__ True
*** __format__ True
*** __ge__ True
*** __getattribute__ True
*** __gt__ True
*** __hash__ True
*** __init__ True
*** __init_subclass__ True
*** __le__ True
*** __lt__ True
__module__ False
*** __ne__ True
*** __new__ True
*** __reduce__ True
*** __reduce_ex__ True
*** __repr__ True
*** __setattr__ True
*** __sizeof__ True
*** __str__ True
*** __subclasshook__ True
__weakref__ False
*** m1 True
*** m2 True
*** m3 True
*** m4 True

vars(), are basically locals() of the class block and returns the functions dumped as a plain function.

m3 *** <classmethod object at 0x1089afbb0>
m4 *** <staticmethod object at 0x1089afcd0>

Whereas getattr() returns the decorator wrapped function:

<bound method C.m3 of <class '__main__.C'>>
<function C.m4 at 0x1050ab940>
Maurice Meyer
  • 17,279
  • 4
  • 30
  • 47
  • Because classmethod and staticmethod objects are not callable unless appropriately wrapped by accessing them through the accessor (which `getattr` calls but `vars` does not). Try `vars(C)['m3']()`, you'll get a type error because it's not callable. – tobyodavies Feb 13 '21 at 12:02
  • So actually I was using the above code to identify methods that could be decorated through a user defined decorator. I wanted to decorate all the methods. But I could not decorate `@classmethod` and `@staticmethod`. So is there a way to extract all method definitions only in a class so that only those class members can be decorated by my user defined decorator – user3282758 Feb 13 '21 at 12:42