当前位置 博文首页 > python两种遍历字典(dict)的方法比较

    python两种遍历字典(dict)的方法比较

    作者:admin 时间:2021-07-10 17:42

    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}
    #结果也是对的
    >>>

    其实,这个例子是我简化过的,我是在一个多线程的程序里发现这个问题的,所以,我的建议是:遍历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()

    中文乱码问题有没有很好的解决办法....?

    jsjbwy