装饰器对有参数的函数进行装饰
前面我们介绍的装饰器,都是对无参数的函数进行装饰,如果要对有参数的函数进行装饰,那么参数如何设置呢?下面,我们先看一段代码:
def wrap(func):
def inner():
print('开始验证权限')
func()
return inner
@wrap
def test(a, b):
print('a=%d,b=%d' % (a, b))
test(1, 2)
运行代码,结果如下所示:
Traceback (most recent call last):
File "<stdin>", line 14, in <module>
test(1, 2)
TypeError: inner() takes 0 positional arguments but 2 were given
上述代码在执行“test(1,2)”时报错,提示inner()函数不需要参数,但是,我们在调用的时候,传递了两个参数。下面我们同样画图来分析。
(1)执行@wrap,等价于test=wrap(test),执行完毕后如图1所示。
图1 执行@wrap
(2)执行代码“test(1,2)”,此时test指向的是inner()函数,程序会执行inner()函数中的代码。可是,创建的inner()函数是不需要参数的,而我们调用test时传入了两个参数,因此程序会报错,提示inner不需要参数,但我们却传入了两个参数。
下面对inner()函数进行修改,在创建inner()函数时添加两个参数,再次调用test()函数,具体代码如下:
def wrap(func):
def inner(a, b):
print('开始验证权限')
func()
return inner
@wrap
def test(a, b):
print('a=%d,b=%d' % (a, b))
test(1, 2)
运行代码,结果如下所示:
开始验证权限
Traceback (most recent call last):
File "<stdin>", line 14, in <module>
test(1, 2)
File "<stdin>", line 4, in inner
func()
TypeError: test() missing 2 required positional arguments: 'a' and 'b'
程序还是报错,同样是缺少函数参数引起的错误。这是因为,在inner()函数内部执行fun()语句时,func()缺少两个参数,具体如图2所示。
图2 程序报错原因分析
再次修改inner()函数,在调用func()时,将a,b参数传入,示例代码如下:
def wrap(func):
def inner(a, b):
print('开始验证权限')
func(a,b)
return inner
@wrap
def test(a, b):
print('a=%d,b=%d' % (a, b))
test(1, 2)
此时,程序输出结果如下:
开始验证权限
a=1,b=2
上面学习的装饰器只是对两个参数的函数适用,如果无法确定函数的参数个数以及参数类型,我们可以使用不定长参数来传递,示例代码如下:
def wrap(func):
def inner(*args, **kwargs):
print('开始验证权限')
func(*args, **kwargs)
return inner
@wrap
def test(*args, **kwargs):
print('----test----')
test()
test(1, 2, 3)
test(a=1,b=2,c=3)
此时,调用不同参数的函数,发现装饰器适用于不同参数的函数,示例代码如下:
开始验证权限
----test----
开始验证权限
----test----
开始验证权限
----test----