装饰器带参数
装饰器本身也是函数,它以闭包的形式存在,且已经存在一个形参(即被修饰的函数)。那么如果装饰器本身在修饰时需要参数才如何写这个装饰器呢?直接看正确代码
#coding=utf-8
def f1_arg(arg):
print('in f1_arg,arg:%s' % arg)
def f1(func):
print('in func,arg:%s' % arg)
def f1_inner():
print('in f1_inner')
func()
return f1_inner
return f1
#装饰器f1_arg修饰f_a时传入的一个字符串yes
@f1_arg('yes')
def f_a():
print('in f_a')
if __name__ == '__main__':
f_a()
结果:
in f1_arg,arg:yes
in func,arg:yes
in f1_inner
in f_a
如上面的@f1_arg('yes')就是一个带参数的装饰器,来看一下它的实现部分。发现在f1_arg中定义了一个闭包f1,然后返回了f1,而闭包f1就是之前常用的装饰器的形式。那整个原理是怎样的呢?
- 先执行f1_arg这个函数,这个函数返回了一个闭包;
- 只用f1_arg的返回值来修饰f_a;
这就是装饰器自身带参数,在实现上就是原来的闭包实现外侧又定义了一个函数,且函数返回内部的闭包。
带参数的装饰器有什么用
假设有函数f_a()和f_b(),目前都要拓展功能,但各自的新需求还不一样,那么用一个装饰器能实现吗?可以!
#coding=utf-8
str1 = '需求1'
str2 = '需求2'
def f1_arg(arg):
print('in f1_arg,arg:%s' % arg)
def f1(func):
print('in func,arg:%s' % arg)
def f1_inner():
print('in f1_inner')
if arg == '需求1':
print('do 需求1')
elif arg == '需求2':
print('do 需求2')
func()
return f1_inner
return f1
@f1_arg('需求1')
def f_a():
print('in f_a')
@f1_arg('需求2')
def f_b():
print('in f_b')
if __name__ == '__main__':
f_a()
print('-' * 10)
f_b()
结果:
in f1_arg,arg:需求1
in func,arg:需求1
in f1_arg,arg:需求2
in func,arg:需求2
in f1_inner
do 需求1
in f_a
----------
in f1_inner
do 需求2
in f_b