python 装饰器装饰类中的方法

目前在中文网上能搜索到的绝大部分关于装饰器的教程,都在讲如何装饰一个普通的函数,本文介绍如何使用Python的装饰器装饰一个类的方法,同时在装饰器函数中调用类里面的其他方法,并以计算一段代码运行时间为例进行说明。

有一个类MySort,在类中有多种排序方法:

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
34
35
36
class MySort(object):
"""docstring for MySort"""
def __init__(self, lis):
super(MySort, self).__init__()
self.r = lis
def bubble_sort(self):
arr = self.r
print arr
flag = 1
for i in range(len(arr) - 1, 1, -1):
for j in range(0, i):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
flag = 0
if flag:
break
flag = 1
print arr
def insert_sort(self):
arr = self.r
print arr
length = len(arr)
for i in xrange(1,length):
if arr[i] < arr[i-1]:
tmp = arr[i]
j = i - 1
while j >= 0 and arr[j] > tmp:
arr[j+1] = arr[j]
j -= 1
arr[j+1] = tmp
print arr
def sort_suc(self):
print '------sort success-------'

为了知道每种算法的运行效率,可以给每个方法增加一个装饰器,但装饰器函数应该写在类里面还是类外面呢?答案是,写在类外面。装饰器函数:

1
2
3
4
5
6
7
def calc_time(fn):
def wrapper(self, *args, **kwargs):
t_start = time.time()
fn(self, *args, **kwargs)
self.sort_suc()
print "{0} used time ======> {1}s".format(fn.__name__, (time.time()-t_start)*1000)
return wrapper

那么既然写在类外面,如何调用这个类的其他方法呢?这又应该怎么办?答案是给wrapper增加一个参数:self, 完整的代码:

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
def calc_time(fn):
def wrapper(self, *args, **kwargs):
t_start = time.time()
fn(self, *args, **kwargs)
self.sort_suc()
print "{0} used time ======> {1}s".format(fn.__name__, (time.time()-t_start)*1000)
return wrapper
class MySort(object):
"""docstring for MySort"""
def __init__(self, lis):
super(MySort, self).__init__()
self.r = lis
@calc_time
def bubble_sort(self):
arr = self.r
print arr
flag = 1
for i in range(len(arr) - 1, 1, -1):
for j in range(0, i):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
flag = 0
if flag:
break
flag = 1
print arr
@calc_time
def insert_sort(self):
arr = self.r
print arr
length = len(arr)
for i in xrange(1,length):
if arr[i] < arr[i-1]:
tmp = arr[i]
j = i - 1
while j >= 0 and arr[j] > tmp:
arr[j+1] = arr[j]
j -= 1
arr[j+1] = tmp
print arr
def sort_suc(self):
print '------sort success-------'
def main():
mylist = [4, 1, 7, 3, 8, 5, 9, 2, 6, 0,123,22]
mysort = MySort(mylist)
mysort.bubble_sort()
if __name__ == '__main__':
main()

运行结果:

1
2
3
4
[4, 1, 7, 3, 8, 5, 9, 2, 6, 0, 123, 22]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 22, 123]
------sort success-------
bubble_sort used time ======> 0.0429153442383s