Python装饰器的理解
Python装饰器(Decorators)用于不改变函数源代码的基础上,对函数添加新的功能。可比如:人的衣服,不改动衣服原材料的情况下,可以在上面加个小红花之类的,哈哈。
装饰器可以作用在,平常购买商品时,点击购买会将购买商品的函数放入进去,如果是登录状态则可以执行这个函数,未登录的话,则跳转到登录界面,不执行购买函数。
在理解Python装饰器前得先理解一下闭包的概念:
博主写了一篇关于闭包的博客,可以参考一下:https://blog.csdn.net/m0_46958731/article/details/110336617
Python装饰器的使用
一个普通计算函数运行时间的装饰器
import time # 记得导入这个时间模块
def run_time(func): # 接收一个函数对象
def wrapper(*args,**kyargs): # 为了防止被装饰函数需要传参
start = time.time()
func(*args,**kyargs) # 调用了传递进来的函数对象
stop = time.time()
print('run %s time is %0.2fs' % (func.__name__,stop - start))
return wrapper # 调用run_time函数后,把wrapper装饰器函数返回给调用者
调用创建好的装饰器
# 定义一个函数,待会被装饰的就是它了
def index():
print('my name is index')
time.sleep(1)
test_index = run_time(index) # 将index函数对象传递进去
# test_index = run_time(index) = wrapper
# 接收到run_time函数的返回值 wrapper的函数对象:test_index = wrapper
test_index() # 调用 wrapper这个装饰器函数
执行效果:
'my name is index'
'run index time is 1.00s'
是不是感觉少了点啥,少了@
装饰器语法糖的使用,但其实装饰器就是就一个方法,添加@
只是少了一行传递被装饰函数的代码
未使用语法糖前
test_index = run_time(index)
# 只是可以自定义变量名,也可以将变量名定义成index
test_index()
使用语法糖以后:把调用代码化简,放在被装饰函数的上方即可
@run_time # run_time(index)
def index():
print('my name is index')
index() # 可以调用装饰好以后index函数了
调用结果:
'my name is index'
'run index time is 1.00s'
@
语法只是将被装饰函数传递到装饰器函数,与未使用@
时调用结果一样
装饰器处理被装饰函数的返回值
相同的代码,处理计算的功能
装饰器写法,几乎没有区别,加入return只是被装饰函数会有返回值
def calculation(func): # 接收一个函数对象
def wrapper(*args, **kyargs): # 为了防止被装饰函数需要传参
print('装饰器将 %s 传递给了 %s 函数' % (args,func.__name__))
res = func(*args, **kyargs) # 将传递给wrapper函数的值交函数对象,这里就是交给下面index函数了
# res拿到index函数的返回值
return res # 将得到的值返回给调用者
return wrapper # 调用run_time函数后,把wrapper装饰器函数返回给调用者
被装饰函数
@calculation
def index(x,y):
print('index接收到了 %s %s 参数' % (x,y))
return x + y # 当调用到index时,返回x+y的处理结果
# 注意:这个index并不是代表上面index函数,因为经历了:index = calculation(index) 将index函数作为对象传递进去
# 然后这个index变量 拿到wrapper的返回对象了,然后index = wraper
# 理解为:index = calculation(index) = wrapper
print('拿到装饰器的返回值:',index(1,10)) # 调用wrapper装饰器函数,并向它传递两个值
执行效果:
'装饰器将 (1, 10) 传递给了 index 函数'
'index接收到了 1 10 参数'
'拿到装饰器的返回值了: 11'
带参数的装饰器
装饰器可以携带参数传入,一个携带参数的装饰器有三层
def outter(parameter): # 接收被调用时传递的参数
print('装饰器接收到的一个参数:',parameter)
def decorators(func):
def wrapper(*args,**kwargs):
func(*args,**kwargs)
return wrapper
return decorators # 将装饰器函数对象,返回给调用者
# 在@语法调用装饰器时,给它传递了一个参数
@outter("this is decorators parameter")
def index():
print('my name is index')
index()
打印结果:
'装饰器接收到的一个参数: this is decorators parameter'
'my name is index'
或许这样看会有些迷惑,但我们恢复成不用@
语法就能通俗易懂了
outter = outter('this is decorators parameter')
# 调用装饰器外层函数,传递一个参数进去,然后它返回了装饰器decorators的函数对象
index = outter(index) # 哈哈,又变成了和上序一样的写法, index = outter(index) = wrapper
index() # 调用wrapper装饰函数
到此为止,装饰器也并没有想象中的那么复杂。
装饰器语法体现了函数作为Python中的一等公民,可以是对象,变量,也可以作为参数和返回值,说明了Python函数的强大与灵活。
技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请
点赞 收藏+关注
谢谢支持!