2012-06-15 101 views
19

好了,所以我有这样的代码:“类方法”对象不是可调用

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" 

我无法弄清楚什么是错用这并会感谢您的帮助。

+0

抱歉未添加错误说明。编辑答案(以及我所知道的这个错误)。如果我有问题的答案,为什么我会发布这个问题? :S 我已经四处寻找这个错误,发现人们得到这些错误,因为他们没有正确使用代码,例如在一个线程中,一个人正在访问像someDict(key)这样的字典元素,并且得到了类似的错误..但是我相信我正在调用一个函数(应该是可调用的,对吗?)。纠正我,如果我错了。 – user1126425

+0

当你得到一个错误,复制粘贴整个堆栈跟踪。它会告诉你有用的东西,比如错误发生在哪一行。 –

+0

Lattye,'Exception TypeError:''classmethod'object is callable“in'pyadecg。__wrap_py_func'ignored'这是我能够在堆栈跟踪中看到的所有内容..感谢您的帮助 – user1126425

回答

12

直到类已经被定义不能创建到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

感谢您的回复休。 1.这真让我感到困惑。为什么python不能在那个地方阻止我,当我用字典来形容它时呢?它只是在我试图打电话时抱怨。 2.这个全局funcList是通过读取配置文件(阅读配置在不同的模块中完成)创建的,所以我想不到另一种方式... 3.我试图获取输入配置文件来告诉程序运行哪些函数,同时这样做是为了保持代码不同部分之间的明确分离(以使其易于扩展) – user1126425

0

添加作为类内的每一个方法的参数。

而且

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

应该是这样的:

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

,不应该之类的体内。

+0

这些都是类方法而非实例方法.. – user1126425

+0

我明白了。你为什么不使用switch语句而不是map?或者你可以使用getattr来调用该方法。那就是如果你把它变成实例方法。 – ulu5

+0

正在尝试在我的代码中优雅......并编写它以便可以轻松扩展:) 我不想将它用作实例方法......因为它会更改某些使用的资源由其他模块,需要以一致的方式查看它们。 – user1126425

2

一类方法包装了一个神奇的对象,它是不是确实可调用给定函数。它只能使用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') 
+0

感谢您的答复Antti。你是否说类方法不可调用?就我而言,我可以通过简单地使用SomeClass.func3(arg1)来调用func3,但问题似乎是用其他函数调用。另外,我需要classmethods,这样我就可以不用在其他模块中实例化这个类(这是我的代码的一种限制)。 – user1126425

+0

为什么不实例化?如果你从来没有实例化类,你不需要一个类。甚至没有班级方法... –

+0

嗯..我认为你是对的。我遵循Java约定..无论如何,它向我介绍了这个问题,我想知道为什么我不能这样做? – user1126425

0

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

@staticmethod 
def function():... 

静态方法不通过类作为隐式第一个参数。

+1

有趣,但它只是导致'TypeError:'staticmethod'对象不可调用“。 – starfry

9

我发现了一些今晚将在这里帮助:我们可以通过解开魔法staticmethodclassmethod对象:getattr(func, '__func__')

我怎么找到这些信息?使用JetBrains的PyCharm(我不知道其他Python IDE),我查看了@staticmethod@classmethod的源代码。这两个类都定义了属性__func__

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

+2

这些只是为pycharm创建的存根,以便代码完成和内省工作。实际上,这些装饰器是用C语言编写的 –