python数据字典遍历删除_python学习——数据字典遍历

本文探讨了在Python中遍历并删除字典元素时可能遇到的问题,建议使用`for k in d.keys()`的方式以避免在迭代过程中改变字典大小导致的异常。同时,文章提及多线程环境下,即使如此也可能出现KeyError,需额外处理。另外,文中对比了带括号和不带括号遍历字典的性能,指出在数据量较大时,不带括号的方式性能更优。
摘要由CSDN通过智能技术生成

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 "", line 1, in

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}

#结果也是对的

>>>

其实,这个例子是我简化过的,我是在一个多线程的程序里发现这个问题的,所以,我的建议是:遍历dict的时候,养成使用 for k in d.keys() 的习惯。

不过,如果是多线程的话,这样就绝对安全吗?也不见得:当两个线程都取完d.keys()以后,如果两个线程都去删同一个key的话,先删的会成功,后删的那个肯定会报 KeyError ,这个看来只能通过其他方式来保证了。

另一篇:dict 两种遍历方式的性能对比

关于纠结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\n")

write("带括号开始时间:")

a=datetime.datetime.now()

s.write(str(a)+"\r\n")

for (d,x) in dict.items():

print "key:"+d+",value:"+str(x)

write("带括号结束时间:")

b=datetime.datetime.now()

write(str(b)+"\r\n")

write("时间间隔:")

write(str(b-a)+"\r\n")

write("不带括号开始时间:") c=datetime.datetime.now() write(str(c)+"\r\n") for d,x in dict.items():     print "key:"+d+",value:"+str(x) write("不带括号结束时间:") d=datetime.datetime.now() write(str(d)+"\r\n") write("时间间隔:") write(str(d-c)+"\r\n") write("\r\n") s.close()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值