如何实现模式事件来调用Python中的classmethod?

时间:2014-07-31 09:23:31

标签: python python-2.7

我想调用某些函数依赖于事件代码我该如何在Python中完成?

我制作了这样的代码,但它不起作用,我只是一步使用它。

class Thing(object):
    @classmethod
    def do1(cls):
        print 'do1'

    @classmethod
    def do2(cls):
        print 'do2'

    eventToMethod = {'1': do1,
                     '2': do2}

    @classmethod
    def onEvent(cls, name):
        method = cls.eventToMethod.get(name)
        if method != None:
            method()

Thing.onEvent('1')

无论我得到这样的错误,并且不知道如何用Python方式调用classmethods。

TypeError: 'classmethod' object is not callable

你能帮忙解决这个简单的问题吗?

3 个答案:

答案 0 :(得分:2)

您需要先对eventToMethod的更改进行一些更改,不要将do1do2分配给它,以便更好地分配字符串。您始终可以使用字符串访问类属性。在词典中存储对do1do2的引用的问题在于,当您存储时,它们不是绑定方法(它们只是classmethod个对象(非数据描述符))它们在字典中,只有在完成类定义后才会转换为完全绑定的类方法。

eventToMethod = {'1': 'do1',
                 '2': 'do2'}

然后使用getaattr获取方法:

@classmethod
def onEvent(cls, name):
    method = getattr(cls, cls.eventToMethod.get(name))
    ...

请注意,您也可以直接将'do1'传递给onEvent,而不是保留字典来存储名称,然后只需使用:

method = getattr(cls, name)

如果您明确调用__get__do1描述符的do2方法,您仍可以使用当前的方法。

method = cls.eventToMethod.get(name)
if method != None:
    method.__get__(None, cls)()

这是有效的,因为这正是Python所做的,classmethod是非数据descriptor,当你Thing.do1时,Python实际上调用__get__方法do1第一个文章为无,第二个为类型:

>>> Thing.do1.__get__(None, Thing)
<bound method type.do1 of <class '__main__.Thing'>>
>>> Thing.do1.__get__(None, Thing)
<bound method type.do1 of <class '__main__.Thing'>>
>>> Thing.do1
<bound method type.do1 of <class '__main__.Thing'>>
>>> Thing.eventToMethod['1'].__get__(None, Thing)   #Using OP's code.
<bound method type.do1 of <class '__main__.Thing'>>

答案 1 :(得分:0)

虽然我知道这并没有直接回答你的问题,但我认为看到替代方案可能会有用。

通常可以使用反射在运行时计算正确的方法。例如:

    @classmethod
    def onEvent(cls, name):
        try:
            method = getattr(cls, 'do%s'%name)
        except AttributeError:
            return

        method()

如果您能够在方法中遵循严格的命名约定,则此方法可能很有用(如示例中,您似乎在前面加上&#39; do&#39;)。它类似于PyUnit如何检测要运行的测试用例集。

这避免了维护dict的需要,这可能与对象上的实际方法不同步。它也可以说是更清晰的代码。

答案 2 :(得分:0)

值得指出的是,如果你试图做一些事件驱动的编程 - 有一些库/框架可以帮助实现这个目的:

示例:

#!/usr/bin/env python

from circuits import Component, Event


class Thing(Component):

    def do1(self):
        print("do1")

    def do2(self):
        print("do2")

    def started(self, manager):
        self.fire(Event.create("do1"))
        self.fire(Event.create("do2"))
        raise SystemExit(0)


Thing().run()

<强>输出:

$ python foo.py
do1
do2

免责声明:我是circuits

的作者