python两种遍历字典(dict)的方法比较
python以其优美的语法和方便的内置数据结构,赢得了不少程序员的亲睐。
其中有个很有用的数据结构,就是字典(dict),使用非常简单。说到遍历一个dict结构,我想大多数人都会想到forkeyindictobj的方法,确实这个方法在大多数情况下都是适用的。但是并不是完全安全,请看下面这个例子:
#这里初始化一个dict >>>d={'a':1,'b':0,'c':1,'d':0} #本意是遍历dict,发现元素的值是0的话,就删掉 >>>forkind: ... ifd[k]==0: ... del(d[k]) ... Traceback(mostrecentcalllast): File"<stdin>",line1,in<module> RuntimeError:dictionarychangedsizeduringiteration #结果抛出异常了,两个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常量。 >>>forkind.keys(): ... ifd[k]==0: ... del(d[k]) ... >>>d {'a':1,'c':1} #结果也是对的 >>>
其实,这个例子是我简化过的,我是在一个多线程的程序里发现这个问题的,所以,我的建议是:遍历dict的时候,养成使用forkind.keys()的习惯。
不过,如果是多线程的话,这样就绝对安全吗?也不见得:当两个线程都取完d.keys()以后,如果两个线程都去删同一个key的话,先删的会成功,后删的那个肯定会报KeyError,这个看来只能通过其他方式来保证了。
另一篇:dict两种遍历方式的性能对比
关于纠结dict遍历中带括号与不带括号的性能问题
for(d,x)indict.items(): print"key:"+d+",value:"+str(x) ford,xindict.items(): print"key:"+d+",value:"+str(x)
带括号和不带括号性能测试结果:
测试结果 测试条数:15 带括号开始时间:2012-06-1412:13:37.375000 带括号结束时间:2012-06-1412:13:37.375000 时间间隔:0:00:00 不带括号开始时间:2012-06-1412:13:37.375000 不带括号结束时间:2012-06-1412:13:37.375000 时间间隔:0:00:00
测试条数:50 带括号开始时间:2012-06-1412:13:57.921000 带括号结束时间:2012-06-1412:13:57.921000 时间间隔:0:00:00 不带括号开始时间:2012-06-1412:13:57.921000 不带括号结束时间:2012-06-1412:13:57.937000 时间间隔:0:00:00.016000 测试条数:100 带括号开始时间:2012-06-1411:53:57.453000 带括号结束时间:2012-06-1411:53:57.468000 时间间隔:0:00:00.015000 不带括号开始时间:2012-06-1411:53:57.468000 不带括号结束时间:2012-06-1411:53:57.531000 时间间隔:0:00:00.063000
测试条数:150 带括号开始时间:2012-06-1412:00:54.812000 带括号结束时间:2012-06-1412:00:54.828000 时间间隔:0:00:00.016000 不带括号开始时间:2012-06-1412:00:54.828000 不带括号结束时间:2012-06-1412:00:54.921000 时间间隔:0:00:00.093000
测试条数:200 带括号开始时间:2012-06-1411:59:54.609000 带括号结束时间:2012-06-1411:59:54.687000 时间间隔:0:00:00.078000 不带括号开始时间:2012-06-1411:59:54.687000 不带括号结束时间:2012-06-1411:59:54.734000 时间间隔:0:00:00.047000
测试条数:500 带括号开始时间:2012-06-1411:54:39.906000 带括号结束时间:2012-06-1411:54:40.078000 时间间隔:0:00:00.172000 不带括号开始时间:2012-06-1411:54:40.078000 不带括号结束时间:2012-06-1411:54:40.125000 时间间隔:0:00:00.047000
测试条数:1000 带括号开始时间:2012-06-1411:54:49.171000 带括号结束时间:2012-06-1411:54:49.437000 时间间隔:0:00:00.266000 不带括号开始时间:2012-06-1411:54:49.437000 不带括号结束时间:2012-06-1411:54:49.609000 时间间隔:0:00:00.172000
测试条数:2000 带括号开始时间:2012-06-1411:54:58.921000 带括号结束时间:2012-06-1411:54:59.328000 时间间隔:0:00:00.407000 不带括号开始时间:2012-06-1411:54:59.328000 不带括号结束时间:2012-06-1411:54:59.687000 时间间隔:0:00:00.359000
测试条数:5000 带括号开始时间:2012-06-1411:55:05.781000 带括号结束时间:2012-06-1411:55:06.734000 时间间隔:0:00:00.953000 不带括号开始时间:2012-06-1411:55:06.734000 不带括号结束时间:2012-06-1411:55:07.609000 时间间隔:0:00:00.875000
测试条数:10000 带括号开始时间:2012-06-1411:55:15.656000 带括号结束时间:2012-06-1411:55:17.390000 时间间隔:0:00:01.734000 不带括号开始时间:2012-06-1411:55:17.390000 不带括号结束时间:2012-06-1411:55:19.109000 时间间隔:0:00:01.719000
测试条数:20000 带括号开始时间:2012-06-1412:19:14.921000 带括号结束时间:2012-06-1412:19:18.593000 时间间隔:0:00:03.672000 不带括号开始时间:2012-06-1412:19:18.593000 不带括号结束时间:2012-06-1412:19:22.218000 时间间隔:0:00:03.625000