Python 函数装饰程序引发位置参数错误?
我正试图编写一个函数装饰器来测试x,y的边界Python 函数装饰程序引发位置参数错误?,python,python-3.x,decorator,python-decorators,Python,Python 3.x,Decorator,Python Decorators,我正试图编写一个函数装饰器来测试x,y的边界 #this is my bound test function def boundtest(func): def onDecorator(self, x, y, *args, **kwargs): print(x, y, *args, **kwargs) assert x in range(self.width) and y in range(self.height) return func(x
#this is my bound test function
def boundtest(func):
def onDecorator(self, x, y, *args, **kwargs):
print(x, y, *args, **kwargs)
assert x in range(self.width) and y in range(self.height)
return func(x, y, *args, **kwargs)
return onDecorator
class Game:
#these are the functions that need bound checking
@boundtest
def at(self, x: int, y: int) -> int:
return self.map[x, y]
@boundtest
def set(self, x: int, y: int, data):
self.map[x, y] = data.value
当我执行game.set(1,1,Color.RED)
时,我得到:
Traceback (most recent call last):
File "C:\Users\Ben\Desktop\Projects\bubble-breaker-bot\game.py", line 61, in <module>
game.set(1, 1, Color.RED)
File "C:\Users\Ben\Desktop\Projects\bubble-breaker-bot\game.py", line 21, in onDecorator
return func(x, y, *args, **kwargs)
TypeError: set() missing 1 required positional argument: 'data'
回溯(最近一次呼叫最后一次):
文件“C:\Users\Ben\Desktop\Projects\bubble breaker bot\game.py”,第61行,在
游戏设置(1,1,颜色,红色)
文件“C:\Users\Ben\Desktop\Projects\bubble breaker bot\game.py”,第21行,在onDecorator中
返回函数(x,y,*args,**kwargs)
TypeError:set()缺少1个必需的位置参数:“数据”
我需要boundtest函数来检查x
和y
是否分别在self.width
和self.height
范围内,同时能够将任意数量的参数传递给它正在装饰的函数
为什么会发生这种情况?装饰符应用于函数对象,而不是绑定方法。这意味着您需要手动传递
self
参数:
Python使用一个名为binding的进程将函数转换为绑定方法,调用绑定方法会自动将绑定到的任何对象作为第一个参数传入;这就是当您在实例上调用函数时,self
被传递到方法中的方式。有关详细信息,请参阅。您可以通过调用生成绑定方法,而不是手动传递self
:
def boundtest(func):
def onDecorator(self, x, y, *args, **kwargs):
print(x, y, *args, **kwargs)
assert x in range(self.width) and y in range(self.height)
bound_method = func.__get__(self, type(self))
return bound_method(x, y, *args, **kwargs)
return onDecorator
当解析
游戏.set
时,该绑定行为应用于装饰程序返回的onDecorator
函数对象,但不应用于包装的func
对象。@heemayl:我添加了通常的说明,并提供了文档链接。是否有更好的方法来编写装饰程序?在PEP20之后,python的禅宗是“简单比复杂好,平面比嵌套好”。如果你问我,嵌套函数似乎有点讨厌。@BenjaminKosten:不知道你为什么这么想。装饰程序需要返回原始函数或替换对象。生成重复使用原始函数的替换的最简单方法是使用嵌套函数对象,然后将原始函数对象作为闭包进行访问。附加的优点是生成的函数对象是唯一的;您可以而且应该使用跨标识信息进行复制。而且,装饰程序大大有助于简化代码的其余部分@BenjaminKosten:但是,如果您觉得这样可以为您生成更清晰的代码,那么您可以看看。
def boundtest(func):
def onDecorator(self, x, y, *args, **kwargs):
print(x, y, *args, **kwargs)
assert x in range(self.width) and y in range(self.height)
bound_method = func.__get__(self, type(self))
return bound_method(x, y, *args, **kwargs)
return onDecorator