python以其優(yōu)美的語法和方便的內(nèi)置數(shù)據(jù)結(jié)構(gòu),贏得了不少程序員的親睞。
其中有個很有用的數(shù)據(jù)結(jié)構(gòu),就是字典(dict),使用非常簡單。說到遍歷一個dict結(jié)構(gòu),我想大多數(shù)人都會想到 for key in dictobj 的方法,確實這個方法在大多數(shù)情況下都是適用的。但是并不是完全安全,請看下面這個例子:
代碼如下:
#這里初始化一個dict
>>> d = {'a':1, 'b':0, 'c':1, 'd':0}
#本意是遍歷dict,發(fā)現(xiàn)元素的值是0的話,就刪掉
>>> for k in d:
... if d[k] == 0:
... del(d[k])
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
#結(jié)果拋出異常了,兩個0的元素,也只刪掉一個。
>>> d
{'a': 1, 'c': 1, 'd': 0}
>>> d = {'a':1, 'b':0, 'c':1, 'd':0}
#d.keys() 是一個下標的數(shù)組
>>> d.keys()
['a', 'c', 'b', 'd']
#這樣遍歷,就沒問題了,因為其實其實這里遍歷的是d.keys()這個list常量。
>>> for k in d.keys():
... if d[k] == 0:
... del(d[k])
...
>>> d
{'a': 1, 'c': 1}
#結(jié)果也是對的
>>>
其實,這個例子是我簡化過的,我是在一個多線程的程序里發(fā)現(xiàn)這個問題的,所以,我的建議是:遍歷dict的時候,養(yǎng)成使用 for k in d.keys() 的習慣。
不過,如果是多線程的話,這樣就絕對安全嗎?也不見得:當兩個線程都取完d.keys()以后,如果兩個線程都去刪同一個key的話,先刪的會成功,后刪的那個肯定會報 KeyError ,這個看來只能通過其他方式來保證了。
另一篇:dict 兩種遍歷方式的性能對比
關于糾結(jié)dict遍歷中帶括號與不帶括號的性能問題
代碼如下:
for (d,x) in dict.items():
print "key:"+d+",value:"+str(x)
for d,x in dict.items():
print "key:"+d+",value:"+str(x)
帶括號和不帶括號性能測試結(jié)果:
代碼如下:
測試結(jié)果
測試條數(shù):15
帶括號開始時間:2012-06-14 12:13:37.375000
帶括號結(jié)束時間:2012-06-14 12:13:37.375000
時間間隔:0:00:00
不帶括號開始時間:2012-06-14 12:13:37.375000
不帶括號結(jié)束時間:2012-06-14 12:13:37.375000
時間間隔:0:00:00
測試條數(shù):50
帶括號開始時間:2012-06-14 12:13:57.921000
帶括號結(jié)束時間:2012-06-14 12:13:57.921000
時間間隔:0:00:00
不帶括號開始時間:2012-06-14 12:13:57.921000
不帶括號結(jié)束時間:2012-06-14 12:13:57.937000
時間間隔:0:00:00.016000
測試條數(shù):100
帶括號開始時間:2012-06-14 11:53:57.453000
帶括號結(jié)束時間:2012-06-14 11:53:57.468000
時間間隔:0:00:00.015000
不帶括號開始時間:2012-06-14 11:53:57.468000
不帶括號結(jié)束時間:2012-06-14 11:53:57.531000
新聞熱點
疑難解答
圖片精選