25

只是想知道在 python 中对事件做出反应的常用方法是什么。在其他语言中有几种方法,如回调函数、委托、侦听器结构等。有没有通用的方法?有哪些默认语言概念或附加模块,您可以推荐哪些?

4

8 回答 8

19

就我个人而言,我认为回调、侦听器和委托之间没有区别。

观察者模式(又名侦听器,又名“多个回调”)很容易实现 - 只需保存一个观察者列表,并从中添加或删除可调用对象。这些可调用对象可以是函数、绑定方法或带有__call__魔法方法的类。您所要做的就是定义您期望从这些接口中获得的接口——例如,它们是否接收任何参数。

class Foo(object):
  def __init__(self):
    self._bar_observers = []

  def add_bar_observer(self, observer):
    self._bar_observers.append(observer)

  def notify_bar(self, param):
    for observer in self._bar_observers:
      observer(param)

def observer(param):
  print "observer(%s)" % param

class Baz(object):
  def observer(self, param):
    print "Baz.observer(%s)" % param

class CallableClass(object):
  def __call__(self, param):
    print "CallableClass.__call__(%s)" % param

baz = Baz()

foo = Foo()

foo.add_bar_observer(observer) # function
foo.add_bar_observer(baz.observer) # bound method
foo.add_bar_observer(CallableClass()) # callable instance

foo.notify_bar(3)
于 2009-01-14T18:07:35.427 回答
2

这完全取决于您的应用程序所需的复杂程度。对于简单的事件,回调可能会做。对于更复杂的模式和解耦级别,您应该使用某种发布-订阅实现,例如PyDispatcher或 wxPython 的 pubsub。

另请参阅此讨论

于 2009-01-14T18:20:02.110 回答
2

我不能说常见的方法,但是这个页面(实际副本不可用)有一个我喜欢的观察者模式的实现。

这是互联网档案链接: http ://web.archive.org/web/20060612061259/http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html

于 2009-01-14T17:43:22.577 回答
1

我使用的大多数 Python 库都为它们的事件通知实现了回调模型,我认为它非常适合这种语言。 Pygtk通过从GObject派生所有对象来做到这一点,它实现了基于回调的信号处理。(尽管这是底层 C GTK 实现的一个特性,而不是受该语言启发的东西。)但是,Pygtkmvc在 Pygtk之上实现了一个观察者模式(和 MVC),这是一项有趣的工作。它使用了一个非常华丽的基于元类的实现,但我发现它在大多数情况下工作得相当好。如果您有兴趣了解完成此操作的一种方式,那么该代码也相当简单易懂。

于 2009-01-14T18:33:55.033 回答
0

我已经看到使用的侦听器和回调。但是AFAIK没有Python方式。如果所讨论的应用程序合适,它们应该同样可行。

于 2009-01-14T17:50:22.607 回答
0

matplotlib.cbook模块包含一个CallbackRegistry您可能想要查看的类。从文档中:

处理一组信号的注册和断开连接
回调:

   信号='吃','喝','快乐'

   定义一个(x):
       打印'吃',x

   def ondrink(x):
       打印“喝”,x

   回调 = CallbackRegistry(信号)

   ideat = callbacks.connect('eat', oneat)
   iddrink = callbacks.connect('drink', ondrink)

   #tmp = callbacks.connect('drunk', ondrink) # 这将引发 ValueError

   callbacks.process('drink', 123) # 将调用 oneat
   callbacks.process('eat', 456) # 会调用 ondrink
   callbacks.process('be merry', 456) # 什么都不会被调用
   callbacks.disconnect(ideat) # 断开连接
   callbacks.process('eat', 456) # 什么都不会被调用

您可能不希望依赖于 matplotlib 包。我建议您简单地将类从源代码复制粘贴到您自己的模块中。

于 2009-01-15T06:39:56.267 回答
0

就个人而言,我只见过使用回调。但是,我还没有看到那么多事件驱动的 python 代码,所以 YMMV。

于 2009-01-14T17:34:58.740 回答
0

我正在寻找一种在 Python 中注册和处理事件的实现。我唯一的经验是使用Gobject,但只使用过 PyGtk。它很灵活,但对于某些用户来说可能过于复杂。我也遇到过其他一些有趣的候选人,但不清楚他们之间的比较。

于 2009-05-12T04:13:31.083 回答