Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 函数装饰程序引发位置参数错误?_Python_Python 3.x_Decorator_Python Decorators - Fatal编程技术网

Python 函数装饰程序引发位置参数错误?

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

我正试图编写一个函数装饰器来测试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, 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