在 Python 中实现事件处理程序 [重复]

Posted

技术标签:

【中文标题】在 Python 中实现事件处理程序 [重复]【英文标题】:Implementing event handlers in Python [duplicate] 【发布时间】:2019-09-16 16:23:41 【问题描述】:

我正在寻找如何实现具有可重写事件处理程序的对象的方法。

这是一个我想调整以使其正常工作的非工作代码:

class Button(object):
  def __init__(self, id):
    self.id = id
    pass
  def trigger_on_press(self):
    self.on_press()
  def trigger_on_release(self):
    self.on_release()
  def on_press(self):
    # empty handler
    print("Just an empty on_press handler from id=%s" % self.id)
    pass
  def on_release(self):
    # empty handler
    print("Just an empty on_release handler from id=%s" % self.id)
    pass

btn = Button("btn")
btn.trigger_on_press()

def custom_handler(self):
  print("Event from id=%s" % self.id)

btn.on_press = custom_handler
btn.trigger_on_press()

如何覆盖该特定实例的默认空 on_press 方法,以便正确传递 self 引用?

【问题讨论】:

pass 语句没用 【参考方案1】:

我建议采用这样的方法:您直接拥有一个属性(在本例中为 func_on_press),该属性包含对函数(而不是方法)的引用。该函数接收一个作为对象的参数(我将其称为 obj 而不是 self 以表明它是一个函数)。

def default_empty_event_handler(obj):
    print('empty handler for id='.format(obj.the_id))

class Button:
    def __init__(self, the_id):
        self.the_id = the_id
        self.func_on_press = default_empty_event_handler
        self.func_on_release = default_empty_event_handler

    def trigger_on_press(self):
        self.func_on_press(self)    # we pass 'self' as argument to the function

    def trigger_on_release(self):
        self.func_on_release(self)  # we pass 'self' as argument to the function

现在您可以随时更改该属性:

btn = Button('btn')
print('first trigger')
btn.trigger_on_press()

def custom_handler(obj):
    print('custom handler for id='.format(obj.the_id))

btn.func_on_press = custom_handler
print('second trigger')
btn.trigger_on_press()

这将给出以下输出:

first trigger
empty handler for id=btn
second trigger
custom handler for id=btn

在我看来,这大大减少了类的代码(您定义的方法更少)并且易于理解。这对你有用吗?

【讨论】:

谢谢,这很好用,但是@Sanyash 引用的重复问题让我更感兴趣。将事件方法调用为普通方法感觉更自然,特别是如果我直接从实例变量中调用它们。【参考方案2】:

关键是在新分配中使用类名而不是对象

btn.on_press = custom_handler 更改为 Button.on_press = custom_handler 并神奇地工作

解释:

当你调用btn.on_press()时,它会被翻译成原来的'Button.on_press(btn)'调用,所以你需要改变蓝图中的调用而不是对象

你的例子:

class Button(object):
  def __init__(self, id):
    self.id = id
    pass
  def trigger_on_press(self):
    self.on_press()
  def trigger_on_release(self):
    self.on_release()
  def on_press(self):
    # empty handler
    print("Just an empty on_press handler from id=%s" % self.id)
    pass
  def on_release(self):
    # empty handler
    print("Just an empty on_release handler from id=%s" % self.id)
    pass

btn = Button("btn")
btn.trigger_on_press()

def custom_handler(self):
  print("Event from id=%s" % self.id)

Button.on_press = custom_handler  # here use the class name not obj name
btn.trigger_on_press()

输出:

Just an empty on_press handler from id=btn
Event from id=btn

【讨论】:

这种方法覆盖了所有实例的类方法。将btx = Button("btx"); btx.trigger_on_press()添加到代码中,您会看到它已经被破坏了。

以上是关于在 Python 中实现事件处理程序 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

在旧版 Win32 应用程序中实现 COM 事件接收器

在python中实现基于事件的状态机 tkinter

使用消息传递接口在 Python 中实现多处理 [关闭]

如何在 DHTMLX 调度程序中实用地添加重复事件?

在SpringBoot中实现异步事件驱动

在SpringBoot中实现异步事件驱动