文章目录
什么是装饰器?
在不修改原函数及其调用方式的情况下对原函数的功能进行扩展。
装饰器的本质是什么?
一个闭包函数
我们来复习一下之前的知识。
def outter():
def inner():
print("我是里层")
print("我是外层")
outter()
"""
运行结果:
我是外层
"""
总结:我们可以看到调用这个outer()方法,只执行了外层函数中的内容,却没有执行内嵌函数中的内容,这是因为没有调用内嵌函数。
def outter():
def inner():
print("我是里层")
print("我是外层")
inner()
outter()
'''
运行结果:
我是外层
我是里层
'''
总结:根据前两段代码,我可以总结,函数不调用,不执行。
大家还记得闭包吗?如果不记得了下面python闭包,复习一下闭包的知识。
python闭包
通过一般方法扩展功能
具备了上面的知识我们就可以通过一般方法扩展功能
def outter(f):
def inner():
print("我是里层")
f()
return inner
def func():
print("我是扩展功能的函数")
outter(func)()
'''
运行结果:
我是里层
我是扩展功能的函数
'''
总结:这其实完成了装饰器的作用,在不改变原函数的调用方式,提高函数的功能。
使用装饰器扩展功能
语法糖:
格式:@装饰器名称
在闭包的基础上,及上面的代码,通过使用装饰器完成装饰。
代码示例:
def outter(f):
def inner():
print("我是里层")
f()
return inner
@outter
def func():
print("我是扩展功能的函数")
func()
'''
运行结果:
我是里层
我是扩展功能的函数
'''
定义一个带参数的装饰器
代码示例:
def outter(f):
def inner(s):
print("我是里层")
f(s)
return inner
@outter
def func(s):
print("我是扩展功能的函数",s)
func("我是从扩展中传进去的参数")
'''
运行结果:
我是里层
我是扩展功能的函数 我是从扩展中传进去的参数
'''
定义一个带任意参数的装饰器
代码示例:
def outter(f):
def inner(*args,**kwargs):
print("我是里层")
f(*args,**kwargs)
return inner
@outter
def func(*args,**kwargs):
print("我是扩展功能的函数",args,kwargs)
func("元组参数1","元组参数2",字典健1="值1",字典健2="值2")
'''
运行结果:
我是里层
我是扩展功能的函数 ('元组参数1', '元组参数2') {'字典健1': '值1', '字典健2': '值2'}
'''
使用@wraps()进行查看被装饰函数的信息
需要导入包from functools import wraps
代码示例:
from functools import wraps
def outter(f):
@wraps(f)
def inner(*args,**kwargs):
print("我是里层")
f(*args,**kwargs)
return inner
@outter
def func(*args,**kwargs):
'''
:param args:位置参数
:param kwargs: 关键词参数
:return: 无返回值
'''
print("我是扩展功能的函数",args,kwargs)
func("元组参数1","元组参数2",字典健1="值1",字典健2="值2")
print(func.__doc__)
print(func.__name__)
'''
运行结果:
我是里层
我是扩展功能的函数 ('元组参数1', '元组参数2') {'字典健1': '值1', '字典健2': '值2'}
:param args:位置参数
:param kwargs: 关键词参数
:return: 无返回值
func
'''
总结:__name__的意思是查看传给形参f的参数是什么。
__doc__查看函数的描述信息
一个函数定义多个装饰器
执行顺序是从里到外,最先调用的是最里层的装饰器,最后调用最外层的装饰器
def outter1(f):
def inner1():
print("执行outter1的f before")
f()
print("执行outter1的f after")
return inner1
def outter2(f):
def inner2():
print("执行outter2的f before")
f()
print("执行outter2的f after")
return inner2
@outter1 #inner1=outter1(inner2)
@outter2 #func=outter2(func)
def func():
print("我是扩展功能的函数")
func()
'''
运行结果:
执行outter1的f before
执行outter2的f before
我是扩展功能的函数
执行outter2的f after
执行outter1的f after
'''
分析:outter1中的f其实是inner2的内存地址,所以执行完print(“执行outter1的f before”)后,会进入到inner2函数中去,执行print(“执行outter2的f before”),这时outter2函数中的f,才是func()函数的内存地址,所以打印了print(“我是扩展功能的函数”),再执行print(“执行outter2的f after”),inner2函数中的东西执行完,回到inner1中去执行print(“执行outter1的f after”)。程序结束。
总结:
比如:
@x
@y
def f():
pass
执行顺序是从里到外,最先调用最里层的装饰器,最后调用最外层的装饰器,它等效于如下:
f=x(y(f))
来一波,推送吧!
群号:781121386
群名:人生苦短,我学编程
欢迎大家加入我们,一起交流技术!!!