Подтвердить что ты не робот

Объект 'classmethod' не может быть вызван

Итак, у меня есть этот код:

class SomeClass:
    @classmethod
    def func1(cls,arg1):
        #---Do Something---
    @classmethod
    def func2(cls,arg1):
        #---Do Something---

    # A 'function map' that has function name as its keys and the above function
    # objects as values
    func_map={'func1':func1,'func2':func2}

    @classmethod
    def func3(cls,arg1):
        # following is a dict(created by reading a config file) that
        # contains func names as keys and boolean as values that tells
        # the program whether or not to run that function
        global funcList
        for func in funcList:
            if funcList[func]==True:
                cls.func_map[func](arg1)        #TROUBLING PART!!!

    if _name__='main'
        SomeClass.func3('Argumentus-Primus')

Когда я запускаю это, я продолжаю получать ошибку:

Exception TypeError: "'classmethod' object is not callable"

Я не могу понять, что с этим не так, и будет благодарен за вашу помощь.

4b9b3361

Ответ 1

Вы не можете создавать ссылки на classmethods до тех пор, пока класс не будет определен. Вам придется переместить его из определения класса. Однако использование глобальной карты функций для определения того, что запускается, действительно неудобно. Если вы описали, что вы пытаетесь сделать с этим, мы могли бы предложить лучшее решение.

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')

Ответ 2

Сегодня я обнаружил что-то полезное: мы можем развернуть магические объекты staticmethod и classmethod через: getattr(func, '__func__')

Как я нашел эту информацию? Используя PyCharm от JetBrains (я не знаю других IDE Python), я просмотрел исходный код для @staticmethod и @classmethod. Оба класса определяют атрибут __func__.

"Остальное остается упражнением для читателя".

Ответ 3

Класс-метод обертывает заданную функцию магическим объектом, который не является вызываемым. Его можно вызывать только с помощью синтаксиса ClassName.method(args).

Я бы не рекомендовал, чтобы вы делали это так, подумайте над тем, чтобы сделать что-то вроде этого:

func_list = {
    'func1': True,
    'func2': False
}

class SomeClass(object):
    def do_func1(self, arg1):
        print("func1", arg1)

    def do_func2(self, arg1):
        print("func2", arg1)

    def run(self, arg1):
        for name, enabled in func_list.items():
            if enabled:
                the_method = getattr(self, 'do_' + name)
                the_method(arg1)


if __name__ == '__main__':
    sc = SomeClass()
    sc.run('Argumentus-Primus')

Ответ 4

Добавить self как аргумент для каждого метода внутри класса.

Кроме

    if _name__='main'
    SomeClass.func3('Argumentus-Primus')

должен выглядеть следующим образом:

if __name__=='__main__':
    SomeClass.func3('Argumentus-Primus')

и не должен находиться внутри тела класса.

Ответ 5

Вам может потребоваться статический метод.

@staticmethod
def function():...

Статические методы не передают класс как неявный первый аргумент.