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
原函数的参数, 也就是传递给原函数的a和b首先会传递给 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)
总而言之: 分清出装饰的对象是谁, 就能理清执行顺序的问题
本文来自博客园,作者:Hello_wshuo,转载请注明原文链接:https://www.cnblogs.com/Hellowshuo/p/15622168.html