【问题标题】:Using decorator to change the return value of a method使用装饰器改变方法的返回值
【发布时间】:2020-08-01 21:07:04
【问题描述】:

我有一个TextBox 和一个Button。当用户点击 Enter 时,我希望单击与 TextBox 相关的特定按钮。 TextBoxButton 是类。我将Button 实例传递给TextBox,以便我们知道应该点击一个。 Button 是一个有 2 个方法 click()autoclick() 的类。

我想要autoclick() 检查是否按下了 Enter 键,如果是,则使click() 返回True。我尝试使用装饰器并编写了这个玩具程序来展示我所尝试的。

class Button:
    def click(self):
        return False

    def autoclick(self, func, *args):
        def wrapper():
            func(*args)# This function needes events as it argumnet
            return True
        return wrapper

b = Button()
class TextBox:
    def __init__(self, button=None):
        self.button = button

    def box(self):
        if enterPressed:
            if self.button is not None:
                self.button.autoclick(self.button.click, events)()


tb = TextBox(button=b)
while True:
    tb.box()
    if b.click():
        print("this needs to be printed when user hits enter")

我没有收到任何错误,但它根本不起作用。

【问题讨论】:

  • tb.button 总是 None,所以 self.button.autoclick(self.button.click, events) 永远不会被执行。
  • 这个问题已经被问过了,所以请随时查看7201715
  • @Jack Song 抱歉,b 本来是要传递给 TextBox,我更新了问题
  • 另一个问题是装饰器实际上从未被调用过。 self.button.autoclick(self.button.click, events) 只返回函数处理程序,但不运行函数。
  • 啊,是的,我又不好了,我更新了问题,对不起

标签: python decorator


【解决方案1】:

我想我可能知道你现在想做什么。

试试这个。这就是我们通常使用装饰器的方式。

class Button:
    @autoclick # this is how decorators are used.
    def click(self):
        return False

    def autoclick(self, func):
        def wrapper(*args):
            func(*args)# This function needes events as it argumnet
            return True
        if enterPressed:
            return wrapper
        else:
            return func

【讨论】:

  • 不,这不起作用。我认为这是因为我们只在 b.click 本身返回 True 而不是 autoclick 时打印一些东西
  • 是的。现在总是 False。
  • 它说自动点击缺少一个必需的位置参数“func”
【解决方案2】:

我认为以下部分需要修改

class TextBox:
   def __init__(self, button=None):
       self.button = button

   def box(self):
       if enterPressed:
           if self.button is not None:
               self.button.autoclick(self.button.click, events)()

类似于:

class TextBox:
    def __init__(self, button=None):
        self.button = button

    def box(self):
        if enterPressed:
            if self.button is not None:
                self.button.click = self.button.autoclick(self.button.click)  # this line is changed

更新

我猜你的意思应该是这样的:

class Button:
    def _click(self):  # Maybe this method have events as parameters?
        return False

    def click(self):
        return self._click()

    def autoclick(self):
        def wrapper(*args):
            self._click(*args)  # This function needs events as it arguments
            self.click = self._click
            return True

        self.click = wrapper


class TextBox:
    def __init__(self, button=None):
        self.button = button

    def box(self):
        if enterPressed:
            if self.button is not None:
                self.button.autoclick()

或者也许是这个? :

class Button:
    def _click(self):  # Maybe this method have events as parameters?
        return False

    def click(self):
        return self._click()

    def autoclick(self):
        def wrapper(*args):
            result = self._click(*args)  # This function needs events as it arguments
            if enterPressed:
                return True
            return result

        self.click = wrapper


class TextBox:
    def __init__(self, button=None):
        self.button = button

    def box(self):
        if self.button is not None:
            self.button.autoclick()

【讨论】:

  • 这在某种意义上是有效的。它将 button.click 设置为 True。但现在我希望它恢复为按钮对象,因此它继续用作按钮而不是布尔值
  • @hippozhipos 它将button.click 设置为一个返回True 的函数,而不仅仅是布尔值True。所以你的意思是你想把button.click转回到被装饰器包裹之前的状态,让它再次成为一个函数返回False
  • 是的,我就是这个意思。
  • @hippozhipos 我更新了我的答案。我希望我的猜测是正确的:)
猜你喜欢
  • 2020-02-29
  • 1970-01-01
  • 2017-06-16
  • 2011-11-04
  • 2020-04-27
  • 2012-11-20
  • 2020-02-10
  • 2015-11-21
  • 2014-05-19
相关资源
最近更新 更多