装饰器
1、开放封闭原则
开放:对于添加新功能是开放的
封闭:对于修改原功能是封闭的
2、装饰器的作用
在不更改原函数调用方式的前提下对原函数添加新功能
3、装饰器
# ①引子——为什么要有装饰器
为了在不修改原函数的基础上为函数添加新功能,产生了装饰器
# ②简单装饰器
def deco(f):
def wrapper():
"""原函数前添加的功能"""
f()
"""原函数后添加的功能"""
return wrapper
def func():
print('这是原函数!')
func = deco(func)
func()
# ③装饰器的语法糖
def deco(f):
def wrapper():
"""原函数前添加的功能"""
f()
"""原函数后添加的功能"""
return wrapper
@deco # ——>此处效果等同于 func = deco(func)
def func():
print('这是原函数')
func()
# ④带返回值的装饰器
def deco(f):
def wrapper():
"""原函数前添加的功能"""
res = f()
"""原函数后添加的功能"""
return res
return wrapper
@deco
def func():
print('这是原函数')
func()
# ⑤带参数、带返回值的装饰器
def deco(f):
def wrapper(*args,**kwargs):
"""原函数前添加的功能"""
res = f(*args,**kwargs)
"""原函数后添加的功能"""
return res
return wrapper
@deco
def func(*args,**kwargs):
print('这是原函数')
func(*args,**kwargs)
# ⑥多层装饰器
# todo
# ⑦多个装饰器修饰同一个函数
# todo
4、装饰器的固定格式
def deco(f):
def wrapper(*args,**kwargs):
"""原函数前添加的功能"""
res = f(*args,**kwargs)
"""原函数后添加的功能"""
return res
return wrapper
@deco
def func(*args,**kwargs):
pring('这是原函数')
func(*args,**kwargs)
5、装饰器的固定格式—wraps版
如果想使用原函数的双下方法,则需要再调用系统装饰器@ wraps(func)
from functools import wraps
def deco(func):
@wraps(func) #加在最内层函数正上方
def wrapper(*args,**kwargs):
return func(*args,**kwargs)
return wrapper
@deco
def origin_func():
'''
这是原函数的注释
:return:
'''
print('这是原函数')
# 虽然已经执行了装饰器,origin_func已经指向wrapper,但是如果用了@wraps(func)装饰器之后调用origin_func的双下方法依然是原函数origin_func的
print(origin_func.__name__)
>>> origin_func
print(origin_func.__doc__)
>>> 这是原函数的注释
>>> :return:
6、带参数的装饰器
def outer(flag):
def timer(func):
def inner(*args,**kwargs):
if flag:
print('''执行函数之前要做的''')
re = func(*args,**kwargs)
if flag:
print('''执行函数之后要做的''')
return re
return inner
return timer
# 此处先执行函数调用outer(False) —> 返回timer —>@timer —>func = timer(func) —> func = inner
@outer(False)
def func():
print(111)
func()
7、多个装饰器装饰同一个函数
def wrapper1(func):
def inner1():
print('wrapper1 ,before func')
func()
print('wrapper1 ,after func')
return inner1
def wrapper2(func):
def inner2():
print('wrapper2 ,before func')
func()
print('wrapper2 ,after func')
return inner2
@wrapper2 # 将inner1进行装饰,即inner1 = wrapper2(inner1) = inner2
@wrapper1 # 先执行这个装饰器,即f = wrapper1(f) = inner1
def f():
print('in f')
f()
# 结果
>>> wrapper2 ,before func
>>> wrapper1 ,before func
>>> in f
>>> wrapper1 ,after func
>>> wrapper2 ,after func