Python中的字典有序无序浅析

一、前言

Python在3.5之前无法保证字典遍历时候与元素添加进入字典时候的顺序一致。而在3.6以后,字典中的元素可以有序遍历,并且相对于3.5也做了空间上的优化。

二、3.5之前

初始化空字典的时候,首先会在内存中初始化一个二维数据,数组8行,3列。二维数组中,3列依次存储hash值,键的内存指针,值的指针。比如:

my_dict = {}

此时的内存示意图
[[---, ---, ---],
[---, ---, ---],
[---, ---, ---],
[---, ---, ---],
[---, ---, ---],
[---, ---, ---],
[---, ---, ---],
[---, ---, ---]]

添加元素时候,首先会根据键计算出hash值,然后根据hash值求出存放内存数组中的索引,然后将键的hash值,键值对的地址添加到数组中三列对应位置。比如:

>>> hash('name')
12709084984489
>>> 12709084984489 % 8
5 # 5即为存放在二维数组中的下标为5的位置

Python自带的 hash函数也是计算出来的,每次关闭开启Py之后的hash函数不同,但是同一次执行过程中键计算出来的值是相同的。
添加多个元素的时候,如果计算出来的hash值冲突,也会采用开放地址等方式处理该问题。比如:

my_dict['age'] = 26
my_dict['salary'] = 999999
此时的内存数组示意图
[[-4234469173262486640, 指向salary的指针, 指向999999的指针],
[1545085610920597121, 执行age的指针, 指向26的指针],
[---, ---, ---],
[---, ---, ---],
[---, ---, ---],
[1278649844881305901, 指向name的指针, 指向kingname的指针],
[---, ---, ---],
[---, ---, ---]]

可以看到先添加的name,在添加的age和salary,但是在内存数组中的顺序却与添加顺序不一致,因此在遍历的时候也顺序也会无序。

对于上述的实现,初始的时候会 开辟固定的内存空间,每一行8X3=24字节。当数据超过数组的2/3空间的时候, 数组会进行扩容,8行变为16行,变为32行。容量变化的同时,根据hash值计算余数求内存数组对应的下标索引也会出现变化,因此插入新数据的时候如果涉及到扩容,可能需要移动数据,效率较低。

三、3.6之后

py3.6之后,初始空字典的时候,底层会有两个数组,一个存放键值对存放内存数组中的索引,一个存放真正的实体。可以看出同样是初始可以存放8个键值对。做了相关的改动和优化。比如

my_dict = {}
此时的内存数组示意图
indices = [None, None, None, None, None, None, None, None]
entries = []

当添加元素的时候,同样会计算hash值,然后取余,不同的是根据取余的结果作为indices数组的索引修改indices数组相应的位置,修改为实际存放数据的第二个数组entries的索引。比如:

>>> hash('name')
4193068542476671
>>> hash('name') % 8
1  # 修改索引数据indices[1]位置

my_dict['name'] = 'kingname'

此时的内存示意图
indices = [None, 0, None, None, None, None, None, None]
indices[1] = 0 表示真实数据是存放在entries[0]的位置
entries = [
    [-5954193068542476671, 指向name的指针, 执行kingname的指针]
  ]

当插入多个元素时候, entries二维数组按照顺序存储插入的元素

my_dict['address'] = 'xxx'
my_dict['salary'] = 999999

此时的内存示意图
indices = [1, 0, None, None, None, None, 2, None]
entries = [
          [-5954193068542476671, 指向name的指针, 执行kingname的指针],
          [9043074951938101872, 指向address的指针,指向xxx的指针],
          [7324055671294268046, 指向salary的指针, 指向999999的指针]
         ]

读取数据时候,根据hash函数计算出hash值,然后求出indices的下标x,根据indices[x]的值就可以读取到真正的键值对,遍历的时候也可以做到 有序遍历。

相比较于3.5之前的版本,空间也做了优化,初始化的时候不需要再固定开辟一个二维数组,只有一个固定长度的indices数组。

Original: https://www.cnblogs.com/welan/p/15920627.html
Author: weilanhanf
Title: Python中的字典有序无序浅析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/621326/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【有手就行】教你做一个树莓派魔镜

    文章目录 Magirror——基于pygame的树莓派魔镜 * (一)功能概览 (二)环境要求 – 1.硬件要求 2.基础软件要求 3.pip包 4.HTTPS API…

    Python 2023年9月20日
    048
  • 利用朴素贝叶斯原理过滤垃圾邮件(TF-IDF算法)

    本人是新手,为了还原该过程用了自己的方法,可能时间复杂度较高,并且在训练数据时也没有用到SKlearn模块中的贝叶斯分类器,是为了尝试自己去还原求后验条件概率这个过程。 目录 一、…

    Python 2023年8月1日
    068
  • 【自动化运维新手村】Flask-2认证

    【摘要】 在Flask专题的上一章节中,主要对Web应用的路由,异常处理和接口返回做了更进一步的讲解,虽然代码更健壮,但离在生产环境中使用还差了最关键的一步,那就是 认证。 认证在…

    Python 2023年8月15日
    058
  • Numpy教程(一)

    目录 demo1-numpy与for循环对比 demo2-向量内(点)积求和(对应位置相乘) demo3-ndarray常见属性 demo4-数组的创建 demo5-批量运算 de…

    Python 2023年8月24日
    051
  • [ML从入门到入门] 支持向量机:从SVM的推导过程到SMO的收敛性讨论

    引言 支持向量机(Support Vector Machine,SVM)在70年代由苏联人 Vladimir Vapnik 提出,主要用于处理二分类问题,也就是研究如何区分两类事物…

    Python 2023年10月20日
    065
  • # BUGKU Simple_SSTI_1-2

    BUGKU Simple_SSTI_1 提示需要传一个flag参数,Flask 是一个微型的 Python 开发的 Web 框架,由上可知flag在secret_key下,conf…

    Python 2023年8月12日
    037
  • PyTorch 基础

    import torch import numpy as np 定义一个三行两列给定元素的矩阵,并且显示出矩阵的元素和大小 torch.Tensor默认的是torch.FloatT…

    Python 2023年8月26日
    046
  • conda,jupyter lab 以及对应插件 的安装和配置

    Jupyter环境安装和配置 * – 1.conda 安装 – 2.创建虚拟环境 – 3.jupyter lab 配置 – 3.ju…

    Python 2023年9月9日
    039
  • 功能测试点大全

    一、 输入框测试 字符型输入框: (1)字符型输入框:英文全半角、数字、空或者空格、特殊字符”~!@#¥%……&*?[]{}&#8221…

    Python 2023年6月12日
    060
  • C++结合libmodbus和matplotlib实现传感器数据的实时图像显示

    本篇的内容结合了博主之前的两篇文章,将传感器数据通过libmodbus读取完成后,利用matplotlib调用窗口,将数据实现可视化。 前期准备:python3 libmodbus…

    Python 2023年9月1日
    041
  • 一招解决所有依赖冲突

    背景介绍 最近遇到了这样一个问题,我们有一个 jar 包 common-tool,作为基础工具包,被各个项目在引用。突然某一天发现日志很多报错。 一看是 NoSuchMethodE…

    Python 2023年10月13日
    054
  • python 日志中最亮的仔,是喜欢的花里胡哨吖…

    这个日志模块好像在清华大学的镜像站里面下载不到,别的镜像站没有试过。我是直接在官网的地址中下载的… 【阅读全文】 C:\Users\Administrator>p…

    Python 2023年11月9日
    045
  • 浅谈深度学习中的概率

    摘要:本次就和大家聊一聊深度学习中的概率。 为什么会用到概率呢?因为在深度学习中经常会需要处理随机的数据,或者包含随机性的任务,随机性也来自非常多的方面,所以在存在不确定性的情况下…

    Python 2023年10月24日
    029
  • Matplotlib画柱状图

    Matplotlib库的导入 导入库import matplotlib.pyplot,柱状图是pyplot的子模块,不能直接导入matplotlib 常用参数详解 matplotl…

    Python 2023年9月3日
    062
  • pandas的Series和DataFrame

    文章目录 pandas的核心类 Series(数据系列)带标签的数组 * 一、创建Series对象 二、Series索引和切片 三、Series的基本用法 – 1.处理…

    Python 2023年8月18日
    054
  • scrapy链接mysql_Scrapy存入MySQL(四):scrapy item pipeline组件实现细节

    Scrapy存入MySQL或是其他数据库,虽然scrapy没有给我们提供拿来就用的类,但是她已经给我们实现了部分方法,我们继承它给我们实现的方法就能轻松的把数据存入你想存入的数据库…

    Python 2023年10月5日
    055
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球