学科分类
目录
基础

装饰器对有参数的函数进行装饰

前面我们介绍的装饰器,都是对无参数的函数进行装饰,如果要对有参数的函数进行装饰,那么参数如何设置呢?下面,我们先看一段代码:

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所示。

img

图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所示。

img

图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----
点击此处
隐藏目录