装饰器
装饰器
1.什么是装饰器
器指的是工具,可以定义成成函数
装饰指的是为其他事物添加额外的东西点缀
合到一起的解释:
装饰器指的定义一个函数,该函数是用来为其他函数添加额外的功能
2.为何要用装饰器
开放封闭原则
开放:指的是对拓展功能是开放的
封闭:指的是对修改源代码是封闭的
装饰器就是在不修改被装饰器对象源代码以及调用方式的前提下为被装饰对象添加新功能
3. 装饰器的使用
3.1 无参装饰器
在使用有参装饰器我们要知道函数和闭包的使用,在此的基础上去使用装饰器,我们直接取一个例子
import time
def index():
time.sleep(3)
print('Welcome to the index page’)
return 200
index() #函数执行
我们要给它添加一个功能,但是呢,我们不能直接在index()函数里面去改动
def timer(func):
def wrapper(): # 引用外部作用域的变量func
start_time=time.time()
res=func()
stop_time=time.time()
print('run time is %s' %(stop_time-start_time))
return res
return wrapper
这样我们就可以改动了
再取一个例子:
import time
def func():
time.sleep(3)
print('老板好同事好大家好')
def timmer(f):
def inner():
start=time.time()
f()
end=time.time()
print(end-start)
return inner
func=timmer(func)
func()
#这样我们就实现了一个timmer装饰器
def home(name):
time.sleep(2)
print('welcome %s to home page' %name)
def outter(func):
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print(stop - start)
return res
return wrapper
# 偷梁换柱:home这个名字指向的wrapper函数的内存地址
home=outter(home)
语法糖
import time
def timmer(func):
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print(stop - start)
return res
return wrapper
# 被装饰对象正上方的单独一行写@装饰器名字
# @timmer # index=timmer(index)
def index(x,y,z):
time.sleep(3)
print('index %s %s %s' %(x,y,z))
@timmer # home=timmer(ome)
def home(name):
time.sleep(2)
print('welcome %s to home page' %name)
index(x=1,y=2,z=3)
home('egon')
2.2有参函数
前面介绍了无参函数,现在这里我们复习有参函数,什么是有参函数呢?有参函数就是在无参函数的前面再套一层函数,这个函数可以有参数,是可以改动,可以传多个值,就是弥补无参函数的缺点,于语法糖@的限制,outter函数只能有一个参数,并且该才是只用来接收被装饰对象的内存地址。
def auth(db_type):
def deco(func):
def wrapper(*args, **kwargs):
name = input('your name>>>: ').strip()
pwd = input('your password>>>: ').strip()
if db_type == 'file':
print('基于文件的验证')
if name == 'egon' and pwd == '123':
res = func(*args, **kwargs) # index(1,2)
return res
else:
print('user or password error')
elif db_type == 'mysql':
print('基于mysql的验证')
elif db_type == 'ldap':
print('基于ldap的验证')
else:
print('不支持该db_type')
return wrapper
return deco
@auth(db_type='file') # @deco # index=deco(index) # index=wrapper
def index(x, y):
print('index->>%s:%s' % (x, y))
@auth(db_type='mysql') # @deco # home=deco(home) # home=wrapper
def home(name):
print('home->>%s' % name)
@auth(db_type='ldap') # 账号密码的来源是ldap
def transfer():
print('transfer')
index(1, 2)
home('egon')
transfer()
有参装饰器模板
def 有参装饰器(x,y,z):
def outter(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
return res
return wrapper
return outter
@有参装饰器(1,y=2,z=3)
def 被装饰对象():
pass
def deco1(func1): # func1 = wrapper2的内存地址
def wrapper1(*args,**kwargs):
print('正在运行===>deco1.wrapper1')
res1=func1(*args,**kwargs)
return res1
return wrapper1
def deco2(func2): # func2 = wrapper3的内存地址
def wrapper2(*args,**kwargs):
print('正在运行===>deco2.wrapper2')
res2=func2(*args,**kwargs)
return res2
return wrapper2
def deco3(x):
def outter3(func3): # func3=被装饰对象index函数的内存地址
def wrapper3(*args,**kwargs):
print('正在运行===>deco3.outter3.wrapper3')
res3=func3(*args,**kwargs)
return res3
return wrapper3
return outter3
# 加载顺序自下而上(了解)
@deco1 # index=deco1(wrapper2的内存地址) ===> index=wrapper1的内存地址
@deco2 # index=deco2(wrapper3的内存地址) ===> index=wrapper2的内存地址
@deco3(111) # ===>@outter3===> index=outter3(index) ===> index=wrapper3的内存地址
def index(x,y):
print('from index %s:%s' %(x,y))
# 执行顺序自上而下的,即wraper1-》wrapper2-》wrapper3
index(1,2) # wrapper1(1,2)