点击上方“Python3X”,选择“置顶或者星标”
第一时间收到精彩推送!
Python Every Day, 第 26 天
装饰器是Python非常重要的一部分,作用是为了增强函数的功能。纯粹的说概念可能看起来比较累,直接以一个简单的例子讲一下吧
比如写一个函数,可以看tokyo.avi(秒懂的去面壁...)
def can_look(age):
print('you can tokyo.avi')
问题来了,如果人人都能看,那岂不是摧残祖国的花朵。因此根据年龄去判断。我们可以这样写
def can_look(age):
if age > 22:
print('you can tokyo.avi')
else:
print('请在家长陪同下观看.')
can_look(age=24)
但是呢,我们今天讲的Python装饰器。那Python装饰器是什么呢?
1、在不修改任何函数的前提下,增加额外的功能。上述方法,就是在修改了原来的函数。一个函数还好,如果很多呢?不仅会破坏代码结构,而且还要写很多重复的代码,并且非常不pythonic.
2、装饰器本身就是一个函数,返回的也是一个函数
Example:
# 定义一个年龄的装饰器
def age_decorator(func):
# 通过*args/**kwargs 进行参数传递
def wrapper(*args, **kwargs):
age = kwargs['age']
if age < 22:
print('请在家长陪同下观看')
else:
print('you can look tokyo.avi')
return func(*args, **kwargs)
return wrapper
# 使用定义的装饰器
@age_decorator
def can_look(age):
print('执行完毕')
can_look(age=28) # 请在家长陪同下观看
输出:
you can look tokyo.avi
执行完毕
如上,@age_decorator 就是我们定义的装饰器,再不修改函数can_look函数的情况下就可以完成我们的功能。这个在Python中也被称为语法糖。
带参数的装饰器
比如我们需要在装饰器中指明年龄,在函数中指明姓名。这种情况该怎么定义装饰器呢?
看下面的例子:
# 接受装饰器的参数
def name_(*nargs, **nkwargs):
# 接收装饰器中的age参数
age = nkwargs['age']
def age_decorator(func):
# 接收函数的参数
def wrapper(*args, **kwargs):
# 接收函数中的name参数
name = kwargs['name']
if age < 22:
print(f'{name}, 你今年{age}岁,请在家长陪同下观看')
else:
print(f'{name} you can look tokyo.avi')
return func(*args, **kwargs)
return wrapper
return age_decorator
# 使用定义的装饰器
@name_(age=19)
def can_look(name):
print('执行完毕')
can_look(name='Tom')
# 输出:
# Tom, 你今年19岁,请在家长陪同下观看
# 执行完毕
很多情况,一个装饰器可能不能满足我们的需求,往往需要多个装饰器。那么他们的执行顺序是怎么样的呢?
请看下面的测试例子,为了方便测试,我特意把装饰b和a调换了位置。
import time
# 定义装饰器b
def decorator_b(func):
print('decorator_b')
def wrapper(*args, **kwargs):
print('wrapper_b')
return func(*args, **kwargs)
return wrapper
# 定义装饰器a
def decorator_a(func):
print('decorator_a')
def wrapper():
time.sleep(1)
print('wrapper_a')
return func()
return wrapper
# 定义装饰器c
def decorator_c(func):
print('decorator_c')
def wrapper():
print('wrapper_c')
return func()
return wrapper
@decorator_a
@decorator_b
@decorator_c
def test():
print('over')
test()
运行结果:
由此可以看出
装饰器由下往上开始装饰(decorator_c - > decorator_b - > decorator_c)
但是执行顺序是从上到下(wrapper_a - > wrapper_b - > wrapper_c)
装饰器是借用面向切面的特性,在不修改函数的情况下,进行方法的增强。在开发过程中,应用场景有很多,如记录日志、记录程序的时间、权限控制等。。