函数修饰器引发位置参数错误?

时间:2018-07-25 20:57:43

标签: python python-3.x decorator python-decorators

我正在尝试编写一个函数装饰器来测试x,y的边界

 #这是我的绑定测试函数
def boundtest(func):
    def onDecorator(self,x,y,* args,** kwargs):
        打印(x,y,* args,** kwargs)
        在range(self.width)中声明x,在range(self.height)中声明y
        返回func(x,y,* args,** kwargs)

    返回onDecorator

类游戏:
    #这些是需要绑定检查的功能

    @boundtest
    def at(self,x:int,y:int)-> int:
        返回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(最近一次通话结束):
  中的文件“ C:\ Users \ Ben \ Desktop \ Projects \ bubble-breaker-bot \ game.py”,行61
    game.set(1,1,Color.RED)
  在onDecorator中的第21行,文件“ C:\ Users \ Ben \ Desktop \ Projects \ bubble-breaker-bot \ game.py”
    返回func(x,y,* args,** kwargs)
TypeError:set()缺少1个必需的位置参数:“ data”
 

我需要boundtest函数来检查 x y 是否在 self.width self.height范围内,同时能够将任意数量的参数传递给正在装饰的函数。

为什么会这样?

1 个答案:

答案 0 :(得分:3)

装饰器应用于函数对象,而不应用于绑定方法。这意味着您需要手动传递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)
        return func(self, x, y, *args, **kwargs)

    return onDecorator

Python使用称为 binding 的过程将函数转换为绑定方法,并且调用绑定方法会自动将绑定的内容作为第一个参数传递;这就是在实例上调用函数时将self传递给方法的方式。有关详细信息,请参见Descriptor HowTo。您可以通过调用invoke descriptor binding manually来生成绑定方法,而无需手动传递self,而是可以func.__get__()

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

该绑定行为应用于解析器在解决{{1}时返回的装饰器返回的onDecorator函数对象,而不应用于包装的game.set对象。