[每日一题]26、一文搞懂Python装饰器

点击上方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)


装饰器是借用面向切面的特性,在不修改函数的情况下,进行方法的增强。在开发过程中,应用场景有很多,如记录日志、记录程序的时间、权限控制等。。





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值