Contents
回的四种写法:记沈崴的dict法术
Zoom.Quiet <zoom.quiet@gmail.com> sender-time Sent at 11:41 (GMT+08:00). Current time there: 11:42 AM. ✆ to python-cn@googlegroups.com cc pythontw@googlegroups.com, guangzhou-tech-party <guangzhou-tech-party@googlegroups.com> date Mon, May 31, 2010 at 11:41 subject Re: [CPyUG] Re: 关于回的四种写法——python的get
2010/5/31 机械唯物主义 : linjunhalida <linjunhalida@gmail.com> > > 写的累死了,不知道发出来有没有意义?
绝对有,至少: - 自个儿重温,并测试明确了大虾的经验 - 给社区留下了活动的文字记要 - 给大虾一个明确的反馈,知道是否讲到位了 - 给有心人一个异步学习的机会 意义大大的哈.,..
原义
昨天聚会,沈大侠分享了一下python dict get的四种方法:
Toggle line numbers
1 # method 1
2 # 采用异常捕捉来处理KeyError
3
4 # 查询1次
5 try:
6 v = data[k]
7
8 except KeyError:
9 v = 12
10
11 # method 2
12
13 # 取值前先进行条件判断
14 # 查询2次
15 if data.has_key(k):
16
17 v = data[k]
18 else:
19 v = 12
20
21
22 # method 3
23 # 和method2类似,只是利用in取代函数调用
24 # 查询2次
25
26 if k in data:
27 v = data[k]
28
29 else:
30 v = 12
31
32 # method 4
33 # 函数调用
34
35 # 查询1次
36 v = data.get(k)
37 if v == None:
38 v = 12
- 提到几点
- 函数调用是比较慢的,不如data[key]和key in data快。
- 所以method2完全可以被method3替代。
- method4在多数情况下也没有method2好。
- 异常处理因为需要建立Error的对象,是最慢的。
- 所以method1不很适用命中率低的状况。
- method1和method4都只查询一次,
- method2和method3都要查询两次,
- 在某些查询是性能瓶颈的时候,不如method1和2快。
- 函数调用是比较慢的,不如data[key]和key in data快。
测试
为了对上面的估计作实际验证,我写了测试程序,如下:
Toggle line numbers
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3 """
4 测试4种dict的get方法
5
6 # method 1
7 # 采用异常捕捉来处理KeyError
8 # 查询1次
9 try:
10 v = data[k]
11 except KeyError:
12 v = 12
13
14 # method 2
15 # 取值前先进行条件判断
16 # 查询2次
17 if data.has_key(k):
18 v = data[k]
19 else:
20 v = 12
21
22 # method 3
23 # 和method2类似,只是利用in取代函数调用
24 # 查询2次
25 if k in data:
26 v = data[k]
27 else:
28 v = 12
29
30 # method 4
31 # 函数调用
32 # 查询1次
33 v = data.get(k)
34 if v == None:
35 v = 12
36
37 """
38 import time, json
39
40 def test(data, k, count):
41 times = []
42 start = time.time()
43 for i in range(count):
44 #method 1
45 try:
46 v = data[k]
47 except KeyError:
48 v = 12
49 end = time.time()
50 print "method 1 spend time: %f s." % (end - start)
51 times.append(end - start)
52
53 start = time.time()
54 for i in range(count):
55 #method 2
56 if data.has_key(k):
57 v = data[k]
58 else:
59 v = 12
60 end = time.time()
61 print "method 2 spend time: %f s." % (end - start)
62 times.append(end - start)
63
64 start = time.time()
65 for i in range(count):
66 #method 3
67 if k in data:
68 v = data[k]
69 else:
70 v = 12
71 end = time.time()
72 print "method 3 spend time: %f s." % (end - start)
73 times.append(end - start)
74
75 start = time.time()
76 for i in range(count):
77 #method 4
78 v = data.get(k)
79 if v == None:
80 v = 12
81 end = time.time()
82 print "method 4 spend time: %f s." % (end - start)
83 times.append(end - start)
84
85 return times
86
87 def main():
88 print "test hit"
89 data = {'a': 12}
90 k = 'a'
91 times1 = test(data, k, 1000000)
92 print
93
94 print "test not hit"
95 data = {'a': 12}
96 k = 'ab'
97 times2 = test(data, k, 1000000)
98 print
99
100 print "test data IO"
101 data = {'a': 12}
102 k = 'a'
103 fd = FileDict(data)
104 times3 = test(fd, k, 5000)
105 print
106
107 import numpy as np
108 import matplotlib.pyplot as plt
109 ind = np.arange(4)
110 p1 = plt.bar(ind, times1, width=0.2, color='r')
111 p2 = plt.bar(ind+0.2, times2, width=0.2, color='g')
112 p3 = plt.bar(ind+0.4, times3, width=0.2, color='b')
113
114 plt.xticks(ind, ('method 1', 'method 2', 'method 3', 'method 4') )
115 plt.legend( (p1[0], p2[0], p3[0]), ('hit', 'not hit', 'IO') )
116
117 plt.show()
118
119 class FileDict:
120 def __init__(self, data):
121 open('temp.txt','w').write(json.dumps(data))
122
123 def get(self, key):
124 return json.load(open('temp.txt'))[key]
125 __getitem__ = get
126
127 def has_key(self, key):
128 return json.load(open('temp.txt')).has_key(key)
129 __contains__ = has_key
130
131 if __name__=="__main__":
132 main()
结果如图(ubuntu9.10 + python2.6):
- method3性能比method2好,method1在not hit的情况下时间消耗最多,
- 在get消耗大的情况下method1和method4消耗的时间要比method2和method3少一半。
反馈
创建 by -- ZoomQuiet [2010-05-31 03:46:44]