Python的学习笔记--装饰器

python的函数也属于一个对象,可以有一个变量来代替,例如前面说过的一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
f=abs
print(f(-10))
```

如果我们在不改变原来函数的前提下,想扩展一个函数的功能。可以重新定义一个函数,把要原函数作为参数传递给`增强函数`,在调用函数前执行一些动作。

```python
def revert(a):
return abs(a)

def new_func(func):
print("do something")
return func

f=new_func(revert)
print(f(-10))

打印结果是:

1
2
do something
10

对于上面的代码,new_func就是装饰器,可以使用@对其进行简化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
def new_func(func):
print("do something")
return func

@new_func
def revert(a):
return abs(a)

print(revert(-10))

```

这样可以省去一个变量的定义,也维持了原来的方法名称。


上面的装饰器有点过于简单,因为我们只能在`return` 语句前增加内容,想在方法后面增加一个确不行,为了能够实现更强大的装饰器,我们可以对其做修改,再增加一层函数:

``` python
def new_func(func):
def inner(a):
print("do something")
res=func(a)
print("something is done")
return res
return inner

@new_func
def revert(a):
print ("processing")
return abs(a)

print(revert(-10))

打印结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
do something
processing
something is done
10
```

上面这个装饰器基本满足了我们的需求,但同样还有一个问题,上面的装饰器,只能传递一个参数,所以还是不够一般性。

我们可以使用函数的默认值的方法来解决这个问题,官方给的是`*args 和 **kwargs`(tuple和dict类型),修改如下:

``` python
def new_func(func):
def inner(*args,**kw):
print("do something")
res=func(*args,**kw)
print("something is done")
return res
return inner
@new_func
def revert(a):
print ("processing")
return abs(a)

print(revert(-10))

我们再增加一个方法:

1
2
3
4
5
6
@new_func
def add(x,y):
print ("processing")
return x+y;
print(add(1,2))

打印结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
do something
processing
something is done
3
```

装饰器也可以传递参数,但是需要更深层次的函数:

``` python
def new_func(text):
print ("call method:",text)
def wapper(func):
def inner(*args,**kw):
print("do something")
res=func(*args,**kw)
print("something is done")
return res
return inner
return wapper

@new_func("revert")
def revert(a):
print ("processing")
return abs(a)

print(revert(-10))

运行结果:

1
2
3
4
5
call method: revert
do something
processing
something is done
10
作者

付威

发布于

2019-03-14

更新于

2020-08-10

许可协议

评论