python装饰器

装饰器作用

装饰器有什么用?
装饰器顾名思义:装饰函数用的, 当我们写一个函数 test 的时候,我们采用一个函数 a来装饰test 函数

def a(func):
    def infun(a,b):
        func(a,b)
    return infun

@a
def test(a,b):
    print(a/b)

test(1,2)

运行输出:

0.5

当然上面这个装饰器a没有任何作用, 但是如果你test函数传递参数为 test(1,0), 就会报错,因为 0不能作为除数, 为了解决这个问题我们在装饰器中加入捕获异常的功能。

def a(func):
    def infun(a,b):
        try:
            func(a,b)
        except Exception as e:
            print(e)            
    return infun

@a
def test(a,b):
    print(a/b)

test(1,0)

运行输出:

division by zero

这里进行了输出,所以成功捕获到了异常, 那么我们来回顾最初的问题装饰器的作用 就是在你装饰的函数的开头或结尾插入一些代码(而且是通过不改变原函数的条件下实现的), 比如这里的容错处理。
可能你会问, 那不使用装饰器直接在原函数 test中进行容错处理, 不就可以了。如果有100个这样的函数你不可能所有函数都要加入try except这种相同的逻辑的, 因为这些逻辑是重复的, 代码一定要考虑是可复用的, 尽可能少重复代码。
另外装饰器可以使代码可维护性提高, 因为你要修改 try except 中捕获的异常也可以通过修改一个装饰器函数来实现, 而不是改100 个函数的逻辑。

装饰器使用方法

首先装饰器函数只有一个参数, 用上面的例子举例, 装饰器函数a唯一的一个参数就是 func, 这里的 func表示的就是被装饰的函数 test(), 另外装饰器内部的 infun() 定义并且返回, infun 的参数就是传递给 test原函数的参数, 也就是传递给原函数的ab首先会传递给 infun() 函数, 最后在装饰器结束的时候返回 infun函数

装饰器函数执行顺序

def a(func):
    print(1)
    def infun(a,b):
        print(3)
        func(a,b)
        print(4)
    print(2)
    return infun

@a
def test(a,b):
    print(a/b)

test(1,10)

执行输出:

1
2
3
0.1
4

通过上面例子可以看出: 执行顺序首先是将装饰器 函数执行结束,然后执行 装饰器内部函数 即,先执行 a() 后执行 infun()

多重装饰器函数执行顺序

如果一个函数使用多个装饰器, 首先要理解的就是, 他们之间的关系, 即装饰的对象是谁?

def b(func):
    print("b函数装饰对象:",func.__name__)
    def b_infun(a,b):
        func(a,b)
    return b_infun

def a(func):
    print("a函数装饰对象:",func.__name__)
    def a_infun(a,b):
        func(a,b)
    return a_infun


@b
@a
def test(a,b):
    print(a/b)

test(1,10)

运行输出:

a函数装饰对象: test
b函数装饰对象: a_infun
0.1

通过这个例子可以看出, a 函数装饰的对象是 test函数, b 函数装饰的对象是 a函数的内部函数 a_infun

那么下面我们来理解这个执行顺序就容易很多了

def b(func):
    print(3)
    def b_infun(a,b):
        print(5)
        func(a,b)
        print(8)
    print(4)
    return b_infun

def a(func):
    print(1)
    def a_infun(a,b):
        print(6)
        func(a,b)
        print(7)
    print(2)
    return a_infun


@b
@a
def test(a,b):
    print(a/b)

test(1,10)

执行输出:

1
2
3
4
5
6
0.1
7
8

首先执行 a函数, 根据我前面说的,执行装饰器函数, 后执行装饰器内部函数, 这个时候执行到 print(2) 装饰器函数执行完毕, 本应该开始执行a_infun函数, 但是由于 a_infun函数又被 b函数所装饰, 那么先执行装饰器函数,开始执行 b函数, 然后执行b函数的内部函数 b_infun 当执行 b_infun 函数到了 func(a,b)的时候, 前面我说的, b函数装饰的是 a_infun函数, 所以开始执行 a_inifun函数,当执行到 func(a,b) a函数装饰的是test(),所以执行test(), 然后执行结束 a_infun, a_infun执行结束相当于 b函数中的 func(a,b)执行结束, 然后最后执行到 print(8)

总而言之: 分清出装饰的对象是谁, 就能理清执行顺序的问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hello_wshuo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值