装饰器的储备知识点
*args **kwargs
名称空间和作用域
函数对象
函数的嵌套定义
闭包函数
回到顶部
1.什么是装饰器
装饰器指的是一种函数,该函数是用来为其他函数添加额外功能的。装饰器本身可以是任何可调用对象,被装饰者也可以是任何可调用对象。
强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
回到顶部
2.为何要用装饰器
在我们将项目运行上线的时候,我们要求的在原有功能上增加新的代码。如果我们将项目的源代码进行修改,很可能导致项目出现bug,下线停运,这是网站运行的大忌,我们需要的是项目一直平稳的运行在服务器上!
因此,我们需要使用装饰器,其功能是开发封闭原则:
开放:指的是对拓展新功能是开放的
封闭:指的是对修改源代码是封闭的
回到顶部
3. 如何使用装饰器
3.1总结无参装饰器模板
def outer(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper
@outer #等于index = outer(index)
def index(name):
print('欢迎来到%s的首页'%name)
index(name)
# 装饰器是为了在不改变源代码和原调用方式的基础上为函数增加新的功能
# 1.先定义一个wrapper函数,在里面调用原函数,并把参数写活和返回原函数的返回值
# 2.然后在wrapper函数内部就可以添加你需要增加的代码功能
# 3.再在wrapper函数外部添加一个函数,这个函数的功能是为了给func函数名传参,闭包的理念传参,在返回内部函数的内存地址
# 4.在外部调用outer函数index = outer(index),说明:第一个outer括号里传的index是指index函数的内存地址,outer(index)返回的值是wrapper的内存地址,被index这个变量接受了(这里index就不在是函数名的内存地址了)
# 5.index(name) 此时调用index,实际是调用了wrapper,传的name参数就被func函数接收了,func函数就等于是原来的index函数
# 6.当我们为另一个函数home增加outer装饰器功能时,还需要写一句home=outer(home),这样就比较麻烦,我们简化了步骤,将装饰器函数放在文件最上方,在需要用到装饰器的地方@一下装饰器名,例如:@outer 其实就等于home=outer(home)了
3.2 总结有参装饰器模板
有参装饰器其实就是在无参装饰器的外面在加了一个闭包!闭包的作用就是为函数进行传参!
def 有参装饰器(x,y,z):
def outer(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper
return outer
@有参装饰器(1,y=2,z=3)
def 被装饰对象():
pass
# 1.@有参装饰器(1,y=2,z=3) 这里会先执行有参装饰器(1,y=2,z=3),向上执行这个函数,然后返回outer内存地址
# 2.接下来@返回的内存地址 例如@outer 等价于执行 index=outer(index)
回到顶部
4. 叠加多个装饰器的加载、运行分析
# 加载顺序是自下往上的
# 执行的顺序是自上往下的
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 outter(x):
def deco3(func3): # func3 就是index的内存地址
def wrapper3(*args,**kwargs):
print('正在运行===>deco3.wrapper3')
res3 = func3(*args,**kwargs)
return res3
return wrapper3
return deco3
@deco1 # 3.index=deco1(wrapper2的内存地址)--->最后index返回的是wrapper1的内存地址
@deco2 # 2. index = deco2(wrapper3的内存地址)-->index又返回成wrapper2的内存地址
@outter(111) # 1.运行outter(111),返回deco3的内存地址-->@deco3==index=deco3(index)--->返回wrapper3的内存地址给index
def index(x,y):
print('from--index %s %s'%(x,y))
index(1,2) # 调用wrapper1,打印wrapper1-->打印wrapper2--->打印wrapper3-->打印index