24

我有这个代码:

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

当我运行它时,我不断收到错误:

异常类型错误:“'classmethod'对象不可调用”

我无法弄清楚这有什么问题,希望您能提供帮助。

4

6 回答 6

18

在定义类之前,您不能创建对类方法的引用。您必须将其移出类定义。然而,使用全局函数映射来决定运行什么真的很尴尬。如果您描述了您要对此做什么,我们可能会建议一个更好的解决方案。

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')
于 2012-06-15T22:20:29.173 回答
13

我今晚发现了一些有用的东西:我们可以通过以下方式解开魔法staticmethodclassmethod物体:getattr(func, '__func__')

我是如何找到这些信息的?使用 JetBrains 的 PyCharm(我不了解其他 Python IDE),我查看了@staticmethod@classmethod. 两个类都定义了属性__func__

“剩下的留给读者练习。”

于 2014-11-17T15:04:54.527 回答
4

class SomeClass所有其他答案都建议在定义之外添加一些代码。在某些情况下可能没问题,但在我的情况下,这非常不方便。我真的很想保留func_map课堂内部。

我建议采用以下方法。不使用类变量,而是使用另一种类方法:

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)

当然,您应该修改此代码,以便每次调用该get_func_map方法时都不会构建新字典。这很容易,我自己并没有这样做以保持示例小而清晰。

在 python 3.6 上测试

于 2018-09-17T15:37:58.297 回答
-1

添加 self 作为类中每个方法的参数。

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

应该是这样的:

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

并且不应该在类的主体内。

于 2012-06-15T21:57:47.390 回答
-1

这是一个不好的方法:

def func3(cls,arg1):
    global funcList
    for func in funcList:
        if funcList[func]==True:
            eval(f'SomeClass.{func}')(arg1)

仅当 func 是函数的名称时才有效。话虽如此,请不要使用此方法,因为您正在接受用户输入。在调用中注入讨厌的代码是很容易的。话虽如此,这确实有效。

于 2018-12-29T04:12:17.150 回答
-2

您可能需要尝试静态方法。

@staticmethod
def function():...

静态方法不会将类作为隐式的第一个参数传递。

于 2013-05-26T14:42:05.953 回答