Various errors in code that tries to call classmethods

I discovered something tonight that will be helpful here: We can unwrap magic staticmethod and classmethod objects via: getattr(func, '__func__')

How did I find this information? Using JetBrains' PyCharm (I don't know about other Python IDEs), I viewed the source code for @staticmethod and @classmethod. Both classes define the attribute __func__.

"The rest is left as an exercise for the reader."


You can't create references to classmethods until the class has been defined. You'll have to move it out of the class definition. However using a global function map to decide what gets run is really awkward. If you described what you are trying to do with this, we could probably suggest a better solution.

class SomeClass(object):
    @classmethod
    def func1(cls, arg1):
        print("Called func1({})".format(arg1))

    @classmethod
    def func2(cls, arg1):
        print("Call func2({})".format(arg1))

    @classmethod
    def func3(cls, arg1):
        for fnName,do in funcList.iteritems():
            if do:
                try:
                    cls.func_map[fnName](arg1)
                except KeyError:
                    print("Don't know function '{}'".format(fnName))

# can't create function map until class has been created
SomeClass.func_map = {
    'func1': SomeClass.func1,
    'func2': SomeClass.func2
}

if __name__=='__main__':
    funcList = {'func1':True, 'func2':False}
    SomeClass.func3('Argumentus-Primus')

All other answers suggest to add some code outside the class SomeClass definition. It may be ok in some cases, but in my case it was very inconvenient. I really wanted to keep the func_map inside the class.

I suggest the following approach. Use not a class variable, but one more classmethod:

class SomeClass:
    # ...

    @classmethod
    def get_func_map(cls):
        return {'func1': cls.func1, 'func2': cls.func2}

    @classmethod
    def func3(cls, arg1):
        # .....
        cls.get_func_map()[func_name](arg1)

Of course you should modify this code so that a new dictionary not be constructed each time you call the get_func_map method. It's easy, I did not do myself it to keep the example small and clear.

Tested on python 3.6