给带参数的函数添加装饰器
在分析 fun_a() 函数装饰器和 fun_b() 函数的关系时,细心的读者可能会发现一个问题,即当 fun_b() 函数无参数时,可以直接将 fun_b 作为 fun_a() 的参数传入。但是,如果被修饰的函数本身带有参数,那应该如何传值呢?
通过上边的例子,我们可以看到,代码fun_b()
实际上执行的是装饰器内层函数function。如果我们要传递参数,就需要function函数可以接收参数,看下边的例子:
def fun_a(func):
def function(arg_b):# 执行内层函数时,把参数传递给内层函数arg_b
print("函数执行前的操作")
res = func(arg_b) # 调用fun_b函数,并把参数arg_b传递给原函数
print("函数执行之后的操作")
return res
return function
@fun_a
def fun_b(arg_b):
print(arg_b)
fun_b("执行fun_b函数") # 实际上执行的是装饰器内层函数function`
fun_b("执行fun_b函数")
调用的是function函数,并把参数给到了arg_b
变量,function内部在执行fun_b函数的时候,把参数传递了过去,
结合之前函数的可变长参数,我们可以把上述装饰器稍作修改,可以使他变得更加通用
def fun_a(func):
def function(*args,**kwargs):# 使用*args,**kwargs来接收任意参数
print("函数执行前的操作")
res = func(*args,**kwargs)
print("函数执行之后的操作")
return res
return function
@fun_a
def fun_b(arg_b):
print(arg_b)
fun_b("执行fun_b函数")`
带参数的装饰器
如果我们想要给装饰器函数传递参数怎么办呢?
再回头看下@装饰器
语法糖
def fun_a(func):
return 'hello'
@fun_a # 这种写法,等价于 fun_b=fun_a(fun_b)
def fun_b():
pass
print(fun_b)`
如果我想要给装饰器传递参数,例如写成如下形式
@fun_a(arg_a) # 该语法糖相当于 funb_b=fun_a(arg_a)(fun_b参数)
def fun_b():
pass`
我们可以看到,上边的例子中,首先调用了一次fun_a函数,然后拿到fun_a函数的返回值,又调用一次,这个就要求fun_a函数的返回值必须是一个函数,所以我们可以把之前的装饰最外层添加一层函数的包裹,就可以给装饰器传递参数了
def fun_a(arg_a): # arg_a接收装饰器传递过来的参数
def swap(func):
def function(*args,**kwargs):
print('接收到了装饰器传递过来的参数',arg_a) #使用装饰器传递的参数
print("函数执行前的操作")
res = func(*args,**kwargs)
print("函数执行之后的操作")
return res
return function
return swap
@fun_a('fun_a')
def fun_b(arg_b):
print(arg_b)
fun_b("执行fun_b函数")`
通过上述例子,我们可以看出,我们只要给不带参的装饰器完成包裹一个方法,就可以实现装饰器中的参数传递
装饰器的应用场景:
1.登录验证
2.函数运行时间统计
3.执行函数之前做准备工作
4.执行函数后清理功能
5.参数校验
网友评论