装饰器
程序员文章站
2022-06-30 14:13:47
...
装饰器
1.装饰器
def w1(func):
def inner():
print("---正在验证权限---")
func()
return inner
@w1 #只要python解释器执行到这个代码那就回自动进行装饰,而不是等到调用的时候才装饰,就相当于 f1 = w1(f1)
def f1():
print("---f1---")
f1()
'''
输出结果:
---正在验证权限---
---f1---
'''
@w1就相当于 f1 = w1(f1) 执行这句话是 func 指向 f1 ,而return inner会直接使inner函数指向的地址直接返回给f1,此时的就指向闭包里面的inner函数,然后函数继续往下运行当运行到 f1() 时,就直接会运行 f1 指向的函数而此时 f1 指向的函数是inner所以就会首先打印 “—正在验证权限—” 继续往下运行会运行到 func() 时,此时func() 是指向原来的f1 函数的地址,所以就会打印原来f1 里面的那句话 “—1---”。这也就是为什么不会去调用f1函数时print("—正在验证权限—")也会被打印 的原因。
调用的时候是从上往下调用,但是装饰的时候是从下往上装饰。
2.两个装饰器
24 def Bold(func):
25 print("正在装饰---1---")
26 def inner():
27 print("---1---")
28 func()
29 return inner
30
31 def Italic(func):
32 print("正在装饰---2---")
33 def inner():
34 print("---2---")
35 func()
36 return inner
37
38
39 @Bold
40 @Italic
41 def f1():
42 print("---结束---")
43 f1()
44'''
45 输出结果:
46 正在装饰---2---
47 正在装饰---1---
48 ---1---
49 ---2---
50 ---结束---
51'''
当两个装饰器一起对函数进行装饰时,是先从下面的装饰器开始装饰,因为装饰器遇到函数才会开始装饰,当程序运行到第一个装饰器时因为下面不是函数程序继续运行,到第二个装饰器时再往下运行就是函数所以就会进行装饰。
3.装饰器对有参数函数进行装饰
1 def func(functionName):
2 print("---func---1---")
3 def func_in(a, b): #如果a,b没有定义,那么会导致第15行的调用失败
4 print("---func_in---1---")
5 functionName(a, b) #如果没有把 a,b当做实参进行传递,那么会导致调用12行的函数失败
6 print("---func_in---2---")
7
8 print("---func---2---")
9 return func_in
10
11 @func
12 def test(a, b):
13 print("---a=%d,b=%d---"%(a, b))
14
15 test(11,22)
16 '''
17 输出结果:
18 ---func---1---
19 ---func---2---
20 ---func_in---1---
21 ---a=11,b=22---
22 ---func_in---2---
23 '''
对不定长的参数进行装饰:
1 def func(functionName):
2 print("---func---1---")
3 def func_in(*args, **kwargs):
4 print("---func_in---1---")
5 functionName(*args, **kwargs)
6 print("---func_in---2---")
7
8 print("---func---2---")
9 return func_in
10
11 @func
12 def test(a,b,c,d):
13 print("---a=%d,b=%d,c=%d,d=%d---"%(a,b,c,d))
14
15 test(11,22,33,44)
16
17 '''
18 输出结果:
19 ---func---1---
20 ---func---2---
21 ---func_in---1---
22 ---a=11,b=22,c=33,d=44---
23 ---func_in---2---
24 '''
4.对带有返回值的函数进行装饰
1 def func(functionName):
2 print("---1---")
3 def func_in():
4 print("---func_---1---")
5 xxx = functionName() #xxx用来保存test函数返回来的haha
6 print("---func_in---2---")
7 return xxx #把haha返回到17行处的ret
8
9 print("---func---2---")
10 return func_in
11
12 @func
13 def test():
14 print("---test---")
15 return "haha"
16
17 ret = test()
18 print("test return value is %s"%ret)
19
20 '''
21 输出结果
22 ---1---
23 ---func---2---
24 ---func_---1---
25 ---test---
26 ---func_in---2---
27 test return value is frank
28 '''
~
如果没有一个变量xxx去接收函数中return的值那么就无法完成装饰。
5.通用装饰器
在实际情况下我们不能去判断它有几个数,有没有返回值所以我们就要用一种通用的装饰器。
1 def func(functionName):
2 def func_in(*arg, **kwargs):
3 print("---记录日志---")
4 ret = functionName(*arg, **kwargs)
5 return ret
6
7 return func_in
8
9 @func
10 def test():
11 print("---test---")
12 return "frank"
13
14 @func
15 def test2():
16 print("---test2---")
17
18 @func
19 def test3(a):
20 print("---test3--a=%d--"%a)
21
22 ret = test()
23 print("test return value is %s"%ret)
24
25 a= test2()
26 print("test2 return value is %s"%a)
27
28 test3(11)
29
30 '''
31 输出结果:
32 ---记录日志---
33 ---test---
34 test return value is frank
35 ---记录日志---
36 ---test2---
37 test2 return value is None
38 ---记录日志---
39 ---test3--a=11--
6.带有参数的装饰器
1 def func_arg(arg):
2 def func(functionName):
3 def func_in():
4 print("---记录日志-arg=%s--"%arg)
5 if arg == "smile": #装饰器中不同的参数可以起到不同的功能
6 functionName()
7 functionName()
8 else:
9 functionName()
10 return func_in
11 return func
12
13
14 #① 先执行func_arg("smile")函数,这个函数return的结果是func这个函数的引用
15 #② 然后就相当于@func
16 #③ 使用@func对test进行装饰
17 @func_arg("smile")
18 def test():
19 print("---test---")
20
21
22 @func_arg("haha")
23 def test2():
24 print("---test2---")
25
26 test()
27 test2()
28
29 '''
30 输出结果:
31 ---记录日志-arg=smile--
32 ---test---
33 ---test---
34 ---记录日志-arg=haha--
35 ---test2---
36 '''
带有参数的装饰器,能够起到在运行时有不同的功能。
上一篇: DrawerLayout的使用
下一篇: 装饰器