-
装饰器的应用场景:
面向对象(OOP)
登录认证
flask路由,全部都是有参装饰器
装饰器:在不修改源代码及调用方式的前提下,额外添加新的功能,符合开放封闭封闭原则就是装饰器:
对额外新增的功能是开放的
对源代码及调用方式是封闭的
# 3个人写的代码,分别计算各自代码运行的时间,但是又不能改变代源代码
import time
# 创建一个装饰器函数
def run_time(f):
'''
计算时间的函数
:param f: 接收要计算时间的函数
'''
def inner();
start_time = time.time()
f()
time.sleep(2)
end_time = time.time()
print(f'{f}运行时间:{end_time-start_time}')
return inner
def func():
print('这是jones写的代码')
def foo():
print('这是tins写的代码')
def fl():
print('这是zhong写的代码')
a = func # a就是func函数
func = run_time # func就是run_time
func(a) # 本质上还是run_time(func),但是不满足调用方式方式封闭
func()
标准版装饰器实现原理:
- 类似于现实中的租房,装饰器就是中介.通过中介来交易
def wrapper(func):
def inner(*args,**kwargs):
# 执行被装饰的函数前
func(*args,**kwargs)
# 执行被装饰的函数后
return inner
def func1():
print('这是jones写的代码')
func = wrapper(func1)
func()
- 类似于淘宝的案例
def tb(func):
def inner(*args,**kwargs):
res = func(*args,**kwargs)
return res
return inner
@tb # 语法糖 store=tb(store)
def store(money):
'''
卖家
'''
print(f'xx名{money}元卖了一个皮包')
return 'lv'
print(store(100)) # 买家花了100
带参数的装饰器:
# arg只是需要满足执行的条件,才能往下执行装饰器
def f(a):
def auth(arg):
def wrapper(func):
def inner(*args,**kwargs):
if arg:
print('开始装饰')
ret = func(*args,**kwargs)
print('装饰成功!')
else:
ret = func(*args,**kwargs)
return ret
return inner
return wrapper
return f
auth = f(1)
@auth(1) # 本质上就是foo = auth(True)(foo)
def func(a):
print(a)
func(10)
=无论有多少个嵌套函数,都是一样的,一层一层解开即可=
多个装饰器装饰一个函数
def wrapper(func):
def inner(*args, **kwargs):
print('is wrapper start')
ret = func(*args, **kwargs)
print('finish wrapper')
return ret
return inner
def wrapper1(func):
def inner1(*args, **kwargs):
print('is wrapper start')
ret1 = func(*args, **kwargs)
print('finish wrapper')
return ret1
return inner1
# 拆语法糖执行顺序
@wrapper # 1.foo = wrapper(foo)
@wrapper1 # 2.foo = wrapper1(foo)
def foo():
print('is foo')
foo() # 3.foo() = inner1()
# 4.foo() = inner()
-----------------------------------------
is wrapper start
is wrapper1 start
is foo
finish wrapper1
finish wrapper
- 多个装饰器的执行顺序是
- 程序是从上往下执行的,所以先解开的语法糖是
wrapper
,再解开wrapper2
,所以输出的是is wrapper start
,在输出is wrapper1 start
- 然而此时的
foo() == inner1()
,因为只调用了一次foo()
所以,往下执行的是finish wrapper1
- 到这wrapper1已经执行完了,而wrapper还没有执行完,所以接着执行
finish wrapper
整个程序执行结束