Python3.7之装饰器
一、装饰器的功能
针对软件开发的“开放-封闭”原则,即:
封闭:已实现的功能代码块不应该被修改
开放:对现有功能的扩展开放
所谓的装饰器,就是通过装饰器函数,来修改原函数的一些功能,使得原函数不需要修改。
二、装饰器引入
1.原有的功能函数如下:
def f1():
print('f1 called: ')
def f2():
print('f2 called: ')
2.现需要对两个功能函数进行权限验证,即需要引入一个闭包函数:
def w1(func):
def inner():
print('----权限验证----')
func()
return inner
review:闭包函数的条件
① 在一个外函数中定义了一个内函数。
② 内函数里运用了外函数的临时变量。
③ 并且外函数的返回值是内函数的引用。
3.装饰后的代码:
# 在执行w1函数的时候,此时直接把inner函数返回了,同时把它赋值给f1
# 此时的f1已经不是未加装饰时的f1了,而是指向了w1.inner函数地址
def w1(func):
def inner():
print('----权限验证----')
func()
return inner
# 当python解释器执行到这句话的时候,会去调用w1函数,同时将被装饰的函数名作为参数传入(此时为f1)
@w1 # f1 = w1(f1)
def f1():
print('f1 called: ')
@w1
def f2():
print('f2 called: ')
# 在调用f1()的时候,其实调用的是w1.inner函数
# 那么此时就会先执行权限验证,然后再调用原来的f1(),该处的f1就是通过装饰传进来的参数f1
f1()
f2()
'''
----权限验证----
f1 called:
----权限验证----
f2 called:
'''
这样下来,就完成了对f1的装饰,实现了权限验证。
三、对有参函数进行装饰
如果原函数有参数,那闭包函数必须保持参数个数一致,并且将参数传递给原方法
1.固定参数:
def w_say(fun):
def inner(name): # 此处应有参数
"""
如果被装饰的函数有形参,那么闭包函数必须有参数
:param name:
:return:
"""
print('say inner called')
fun(name) # 将参数传给原方法
return inner
@w_say
def hello(name):
print('hello ' + name)
hello('Vivian')
'''
say inner called
hello Vivian
'''
2.非固定参数:
def w_add(func):
def inner(*args):
print('add inner called')
func(*args)
return inner
@w_add # 共有装饰器,被装饰的函数的形参不固定
def add(a, b): # 被装饰的函数有形参
print('%d + %d = %d' % (a, b, a + b))
@w_add
def add2(a, b, c):
print('%d + %d + %d = %d' % (a, b, c, a + b + c))
add(2, 4)
add2(2, 4, 6)
'''
add inner called
2 + 4 = 6
add inner called
2 + 4 + 6 = 12
'''
四、对带有返回值的函数进行装饰
def w_test(func):
def inner():
print('w_test inner called start')
# 对test进行调用之后,接收返回值s
str0 = func() # 原test的返回值传递给str0
print('w_test inner called end')
# 被装饰之后的test返回值为str0
return str0
return inner
@w_test # test = w_test(test)
def test():
print('this is test fun')
return 'hello'
ret = test()
print('ret value is %s' % ret)
'''
w_test inner called start
this is test fun
w_test inner called end
ret value is hello
'''