【问题标题】:python add an attribute to a method using decoratorspython使用装饰器为方法添加属性
【发布时间】:2023-03-10 01:50:01
【问题描述】:

我正在尝试使用装饰器向我的方法添加一个属性,以确定它是否已被调用。我不知道为什么会出现这个错误:TypeError: bet() missing 1 required positional argument: 'betsize'。

文件game.py

class Game(object):
    def __init__(self):
        ..

    @AddCalled
    def bet(self, betsize):
        print(betsize)

文件 addcalled.py :

class AddCalled(object):
    def __init__(self, f):
        self.f = f
        self.called = False

    def __call__(self, *args, **kwargs):
        self.f(*args, **kwargs)
        self.called = True

我从 Qt 信号(按钮单击)中获得下注大小。目标槽函数是 game.py 中的 bet()

文件 mainui.py

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
    ..

    self.connect(self.ui.btnBet, SIGNAL("clicked()"), self.bet)

    def bet(self):
        #assuming 'game' is an instance of Game()
        self.game.bet(self.ui.betLine.text())

现在每次点击下注按钮时都会出现此错误

Traceback (most recent call last):
  File "/home/njl/projet/mainui.py", line 27, in bet
    self.game.bet(self.ui.betLine.text())
  File "/home/njl/projet/addcalled.py", line 15, in __call__
    self.f(*args, **kwargs)
TypeError: bet() missing 1 required positional argument: 'betsize'

我将不胜感激。简直卡在里面了。

【问题讨论】:

  • 您的代码有错误:您使用self.f 将函数存储在__init__ 中,但是您尝试在call 中使用self.func 访问它。
  • 顺便注意,将属性存储在方法上只会在方法被任何实例调用时设置一次;它不会告诉您是否在Game 的给定实例上调用了bet。这是否重要取决于您打算如何使用called 属性。
  • 抱歉,我的代码实际上写得很好。我刚刚编辑了它@BrenBarn
  • 是的,弄错了。我需要重新考虑一下。感谢以下解决方案

标签: python qt class decorator


【解决方案1】:

您的装饰器没有正确地将 self 传递给包装函数。

通常,self 是由函数对象的描述符机制添加的,该机制将它们即时转换为带有 self 滚动的方法对象。但是您将方法替换为 AddDecorator 对象,该对象没有实现描述符协议,所以当你的 AddDecorator 包装器被调用时,它不知道它被调用的是什么实例(即 self 应该是什么)。

你可以在你的 AddDecorator 类上实现描述符协议,方法是给它一个__get__ 方法。或者你可以使用一个函数编写一个普通的装饰器:

def addCalled(func):
    def newFunc(*args, **kwargs):
        newFunc.called = True
        func(*args, **kwargs)
    newFunc.called = False
    return newFunc

【讨论】:

    【解决方案2】:

    当你写作时:

    @AddCalled
    def bet(self, betsize):
        print(betsize)
    

    这相当于:

    def bet(self, betsize):
        print(betsize)
    
    bet = AddCalled(bet)
    

    因此,传递给AddCalled 的参数是bet 函数。

    【讨论】:

    • 发生了什么?我正在阅读您的帖子,然后您将其删除:/
    • @BrenBarn 的解决方案是正确的。除了我更喜欢蛇案例函数名称;-)。我也同意它关于你如何标记电话的评论。
    猜你喜欢
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 2014-06-25
    • 1970-01-01
    • 2011-07-25
    • 2021-03-11
    • 1970-01-01
    • 2021-12-15
    相关资源
    最近更新 更多