1
class ExFunc:

    @classmethod
    def exFunc(cls):
        print("exFunc has worked")
    
    func = exFunc
    funcs = [exFunc]


ExFunc.funcs[0]()

and i get TypeError: 'classmethod' object is not callable error in ExFunc.funcs0 line. I have some other functions in original code so i want to add them into a list and call them from list according to the input of the user. How can i do it?

I printed the ExFunc.funcs[0] code and it says its a classmethod and i tried to add () at its end because i thought i normally call functions when i put () at the end but it didnt work.

Kaitsuke
  • 13
  • 2
  • 2
    You can call it via descriptor `ExFunc.funcs[0].__get__(ExFunc)()` https://docs.python.org/3/howto/descriptor.html#simple-example-a-descriptor-that-returns-a-constant – Andrej Kesely Jul 24 '23 at 20:40
  • Seen this? https://stackoverflow.com/questions/63567832/how-to-overcome-classmethod-is-not-callable-in-python – OneCricketeer Jul 24 '23 at 20:40
  • 3
    There are other options here. Given that `exFunc` doesn't use its `cls` argument at all, there's an argument to be made that it should be a static method, or just a standalone function. You might also want `funcs` to store not the class method, but the underlying function (`exFunc.__func__`). – chepner Jul 24 '23 at 20:42

2 Answers2

3

classmethod objects are not callable, they "become" callable when you invoke them from either an instance of the class or the class itself. In that case Python turns them into a "method object" which has an object(the reference to the class) bound to it.

how is that possible? classmethods are descriptors.

You can mimic that magic I talked above, manually using the __get__ method. Note that you could pass an instance of that class as well.:

# simulating when it's called from the class
method = ExFunc.funcs[0].__get__(None, ExFunc)
method()

# simulating when it's called from an instance of the class
obj = ExFunc()
method = ExFunc.funcs[0].__get__(obj)
method()

There is however another solution, you can get the underlying function out of a classmethod object using __func__. Just note that it's a plain function with a parameter. You need to pass that:

ExFunc.funcs[0].__func__(ExFunc)
S.B
  • 13,077
  • 10
  • 22
  • 49
0

A class method is associated with the class.

To call the class method you defined, you have to do ExFunc.exFunc().

If you want to call the method from a list, consider storing ExFunc in the list.

For more details, see: A better way to call Class Methods from List of Class Objects - Python

Harley Sun
  • 35
  • 6