python学習-データ辞書の遍歴

7217 ワード

pythonはその優美な文法と便利な内蔵データ構造で、多くのプログラマーの愛顧を勝ち取った.その中には、辞書(dict)という便利なデータ構造があります.とても簡単に使えます.dict構造を巡ると、for key in dictobjの方法を思い浮かべる人が多いと思いますが、確かにこの方法は多くの場合適用されます.しかし、完全に安全ではありません.次の例を見てください.
 
  
# dict
>>> d = {'a':1, 'b':0, 'c':1, 'd':0}
# dict, 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
# , 0 , 。
>>> d
{'a': 1, 'c': 1, 'd': 0}

>>> d = {'a':1, 'b':0, 'c':1, 'd':0}
#d.keys()
>>> 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}
#
>>>

実は、この例は私が簡略化したもので、私は1つのマルチスレッドのプログラムの中でこの問題を発見したので、私の提案はdictを遍歴する時、for k in d.keys()を使う習慣を身につけることです.
しかし、マルチスレッドであれば、これで絶対に安全ですか?必ずしもそうではありません:2つのスレッドがd.keys()を取った後、2つのスレッドが同じkeyを削除すれば、先に削除するのは成功し、後に削除するのは必ずKeyErrorに報告されます.これは他の方法で保証するしかないようです.
もう一つ:dictの2つの遍歴方式の性能の対比
葛藤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)

かっこ付きおよびかっこなしのパフォーマンステストの結果:
 
  

:15
:2012-06-14 12:13:37.375000
:2012-06-14 12:13:37.375000
:0:00:00
:2012-06-14 12:13:37.375000
:2012-06-14 12:13:37.375000
:0:00:00

:50
:2012-06-14 12:13:57.921000
:2012-06-14 12:13:57.921000
:0:00:00
:2012-06-14 12:13:57.921000
:2012-06-14 12:13:57.937000
:0:00:00.016000
:100
:2012-06-14 11:53:57.453000
:2012-06-14 11:53:57.468000
:0:00:00.015000
:2012-06-14 11:53:57.468000
:2012-06-14 11:53:57.531000
:0:00:00.063000

:150
:2012-06-14 12:00:54.812000
:2012-06-14 12:00:54.828000
:0:00:00.016000
:2012-06-14 12:00:54.828000
:2012-06-14 12:00:54.921000
:0:00:00.093000

:200
:2012-06-14 11:59:54.609000
:2012-06-14 11:59:54.687000
:0:00:00.078000
:2012-06-14 11:59:54.687000
:2012-06-14 11:59:54.734000
:0:00:00.047000

:500
:2012-06-14 11:54:39.906000
:2012-06-14 11:54:40.078000
:0:00:00.172000
:2012-06-14 11:54:40.078000
:2012-06-14 11:54:40.125000
:0:00:00.047000

:1000
:2012-06-14 11:54:49.171000
:2012-06-14 11:54:49.437000
:0:00:00.266000
:2012-06-14 11:54:49.437000
:2012-06-14 11:54:49.609000
:0:00:00.172000

:2000
:2012-06-14 11:54:58.921000
:2012-06-14 11:54:59.328000
:0:00:00.407000
:2012-06-14 11:54:59.328000
:2012-06-14 11:54:59.687000
:0:00:00.359000

:5000
:2012-06-14 11:55:05.781000
:2012-06-14 11:55:06.734000
:0:00:00.953000
:2012-06-14 11:55:06.734000
:2012-06-14 11:55:07.609000
:0:00:00.875000

:10000
:2012-06-14 11:55:15.656000
:2012-06-14 11:55:17.390000
:0:00:01.734000
:2012-06-14 11:55:17.390000
:2012-06-14 11:55:19.109000
:0:00:01.719000

:20000
:2012-06-14 12:19:14.921000
:2012-06-14 12:19:18.593000
:0:00:03.672000
:2012-06-14 12:19:18.593000
:2012-06-14 12:19:22.218000
:0:00:03.625000


dictの数は200以下では括弧付きの方が性能が高いが、200以上のデータの後で括弧なしの実行時間は少ないことがわかる.
次はテストコードです.
 
  
Code
#-*- coding: utf-8 -*-
import datetime,codecs

dict = {}

for i in xrange(0,20000):
    dict.setdefault("name"+str(i))
    dict["name"+str(i)]="name"

s=codecs.open(r'c:\\dict.txt','a', 'utf-8')

def write(des):
    s.write(des.decode("utf-8"))

write(" :")
write(str(len(dict))+"\r
")
write(" :")
a=datetime.datetime.now()
s.write(str(a)+"\r
")

for (d,x) in dict.items():
    print "key:"+d+",value:"+str(x)
write(" :")
b=datetime.datetime.now()
write(str(b)+"\r
")
write(" :")
write(str(b-a)+"\r
")

write(" :")
c=datetime.datetime.now()
write(str(c)+"\r
")
for d,x in dict.items():
    print "key:"+d+",value:"+str(x)
write(" :")
d=datetime.datetime.now()
write(str(d)+"\r
")
write(" :")
write(str(d-c)+"\r
")
write("\r
")
s.close()