简体   繁体   English

如何实现模式事件以在Python中调用类方法?

[英]How can I implement pattern event to call classmethod in Python?

I want to call some function depend on event code how can I do it in Python? 我想根据事件代码调用某些函数,如何在Python中实现呢?

I made such code but it not works and I am user that only one step to make it working. 我编写了这样的代码,但是它不起作用,并且我认为仅一步之遥就可以使它起作用。

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

Whatever I get such errors and has not idea how to call classmethods in Python way. 无论我收到这样的错误,并且不知道如何以Python方式调用类方法。

TypeError: 'classmethod' object is not callable

Can you help with this simple problem? 您可以解决这个简单的问题吗?

You need to make some changes to changes to eventToMethod first, don't assign do1 , do2 to it, better assign strings. 你需要做出一些改变,以改变eventToMethod第一,不分配do1do2它,更好地分配字符串。 You can always access class attributes using strings. 您始终可以使用字符串访问类属性。 The problem with storing references to do1 and do2 in dictionary is that they are not bound methods yet(they're simply classmethod objects(non-data descriptors)) when you store them in dictionary, it's only after the completion of class definition that they're converted to fully bound class methods. 与存储到引用的问题do1do2在字典的是,他们不绑定方法,但(他们只是classmethod的对象(非数据描述符))当您将它们存储在字典中,只有类定义完成后就是他们转换为完全绑定的类方法。

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

And then use getaattr to get the method: 然后使用getaattr来获取方法:

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

Note that you can also directly pass 'do1' to onEvent instead of keeping a dictionary to store names and then simply use: 请注意,您也可以直接将'do1'传递给onEvent而不用保留字典来存储名称,然后简单地使用:

method = getattr(cls, name)

You can still get away with your current approach if you call __get__ method of do1 , do2 descriptors explicitly.: 如果你打电话,你仍然可以摆脱当前的做法__get__的方法do1do2明确描述符:

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

This works because this is exactly what Python does under the hood, classmethod is a non-data descriptor and when you do Thing.do1 Python actually calls __get__ method of do1 with first agument as None and second as type: 这工作,因为这正是Python的引擎盖下呢, classmethod是一种非数据descriptor ,当你做Thing.do1的Python实际调用__get__的方法do1与第一agument为None和第二类型:

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

While I understand that this doesn't answer your question directly, I thought it might be useful to see an alternative. 虽然我知道这不能直接回答您的问题,但我认为查看替代方法可能会很有用。

Often it's possible to use reflection to calculate the correct method at runtime. 通常可以在运行时使用反射来计算正确的方法。 For example: 例如:

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

        method()

This approach may be useful if you are able to follow a strict naming convention in your methods (as in the example, where you seem to prefix them with 'do'). 如果您能够在方法中遵循严格的命名约定(例如,在示例中似乎用“ do”作为前缀),则此方法可能很有用。 It's similar to how PyUnit detects the set of test cases to run. 这类似于PyUnit检测要运行的测试用例集的方式。

This avoids the need to maintain a dict, which may get out of sync with the actual methods on the object. 这避免了维护一个dict的需要,该dict可能与对象上的实际方法不同步。 It also arguably leads to clearer code. 可以说它还可以导致更清晰的代码。

It's worth pointing out as well that if you are attempting to do some kine of event-driven programming -- There are libraries/frameworks that help facilitate this: 值得指出的是,如果您尝试进行事件驱动的编程,那么有一些库/框架可以帮助实现这一点:

Example: 例:

#!/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()

Output: 输出:

$ python foo.py
do1
do2

Disclaimer: I'm the author of circuits 免责声明:我是电路的作者

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM