• 为什么Python3.6字典变得有序了?


    其实 在你看了笔者的文章之前,或许想过这样一个问题, 

      为什么列表是有顺序的呢?而字典不是?

        来看一下在内存中是怎样存储的就知道了:

          列表的存储是顺序存储,就像你上大学老师会点名的花名册一样,写的时候按顺序写,读的时候也是按顺序读的.

          而字典,在Python3.5之前,不能说无序,只能说不确定,时而有序是而无序.存储结构是hash表,是通过索引查找数据,所以存储的位置很随机,而读取是顺序读取得,因此写入和读取得顺序不同。他的旧结构就是这样的了

    --+-------------------------------+
      | 哈希值 (hash)  键 (key)  值 (value)
    --+-------------------------------+
    0 |    hash0      key0    value0
    --+-------------------------------+
    1 |    hash1      key1    value1
    --+-------------------------------+
    2 |    hash2      key2    value2
    --+-------------------------------+
    . |           ...
    __+_______________________________+

        那我们再来看一下结构

    Indices
    ----------------------------------------------------
    None | index0 | None | None | index2 | None | index1 ...
    ----------------------------------------------------
    
    Entries
    --------------------
    hash0   key0  value0
    ---------------------
    hash1   key1  value1
    ---------------------
    hash2   key2  value2
    ---------------------
            ...
    ---------------------

    新结构由 Indices(索引,数组实现) 和 Entries(实体,PyDictObject类型) 两种结构组成。

    • 当插入一个数据时,先计算数据对应的hash值并映射成 Indices 数组的一个下标,没有冲突的话就将另一个值 Entries_index(暂时这么叫吧) 填入Indices数组中下标对应的位置。并在Entries后面追加一行记录,类似 hash值, key值, value值 。如果冲突的话可以用基本的解决冲突的办法,这里不赘述了。

    这种方法,字典 增删改查的时间复杂度 会有以前的O(1) 变为O(2),因为多了一步查找的过程。而且字典扩容和缩容时要按照Indices的顺序来保持字典始终有序。

    但是至少有两个优化。

    • 字典占用的内存变小了。旧的字典总会预留大于 1/3的容量的hash位置,防止hash碰撞过多影响效率。现在则不必预留。
    • 字典有序了。

    https://github.com/python/cpython/blob/3d75bd15ac/Include/dictobject.h#L23

  • 相关阅读:
    asp.net图片上传代码
    C#(同步调用、异步调用、异步回调)
    跨线程的控件调用
    C# ListView用法详解 很完整
    获取dataGridView双击时判断双击的是下面的行,还是列头
    加密解密类
    C# 中DataGridView 绑定List<T>做数据源的操作问题
    C#获取当前程序集的完整路径
    接口测试-小结
    接口测试用例
  • 原文地址:https://www.cnblogs.com/well-666/p/12097260.html
Copyright © 2020-2023  润新知