Python序列之字典

系列文章目录

  1. Python序列之列表
  2. Python序列之元组
  3. Python序列之字典(本篇文章)
  4. Python序列之集合

Python序列之字典

  • 系列文章目录
  • 前言
  • 一、字典是什么?
  • 二、字典的操作
    • 1.创建
      • (1)通过`{}`、`dict()`创建
      • (2)通过`zip()`创建
      • (3)通过`fromkeys()`创建值为空的字典
    • 2.元素的访问
      • (1)通过`[键]`获得“值”。
      • (2)通过`get()`方法获得“值”。
      • (3)列出所有的键值对、所有的键、所有的值
      • (4)用`len()`计算键值对的个数
      • (5)用`in`检测一个键是否在字典中
    • 3.元素的添加、修改、删除
      • (1)给字典新增"键值对"。
      • (2)使用`update()`将新字典中所有键值对全部添加到旧字典对象上。
      • (3)删除元素:`del()`、`clear()`与`pop()`
      • (4)`popitem()`:随机删除和返回该键值对。
    • 4.序列解包
    • 5.练习:用字典对表格数据进行存取
  • 三、字典的底层原理(重要)
    • (1)存储键值对的过程
    • (2)查找值对象的过程
  • 总结


前言

前面我们已经讲了Python中的列表:Python序列之列表和元组:Python序列之元组
。今天我们再来看一下Python中另一种常用的序列——字典。

一、字典是什么?

字典是 “键值对”的无序可变序列。字典中的每个元素都是一个“键值对”,包含:“键对象"和"值对象”,即key:value对,可以通过“键对象"实现快速获取、删除、更新对应的"值对象"。
在这里插入图片描述
一个典型的字典的定义方式:

a = {'name': 'yyy', 'age': 3, 'job': 'programmer'}

列表中我们通过”下标数字"找到对应的对象,字典中通过“键对象“找到对应的“值对象”

  • “键”是任意的不可变数据,比如:整数、浮点数、字符串、元组。
  • 但是:列表、字典、集合这些可变对象,不能作为“键”。
  • 并且“键”不可重复
  • “值”可以是任意的数据,并且可重复。

二、字典的操作

1.创建

(1)通过{}dict()创建

a = {'name': 'yyy', 'age': 3, 'job': 'programmer'}
b = dict(name='yyy', age=3, job='programmer')
c = dict([('name', 'yyy'), ('age', 3), ('job', 'programmer')])
d = {}  # 创建一个空字典
e = dict()  # 创建一个空字典print(a)  # 输出:{'name': 'yyy', 'age': 3, 'job': 'programmer'}
print(b)  # 输出:{'name': 'yyy', 'age': 3, 'job': 'programmer'}
print(c)  # 输出:{'name': 'yyy', 'age': 3, 'job': 'programmer'}
print(d)  # 输出:{}
print(e)  # 输出:{}

(2)通过zip()创建

既然可以用上面创建c的方式创建字典,那自然可以用zip()函数:

keys = ['name', 'age', 'job']
values = ['yyy', '3', 'programmer']
d = dict(zip(keys, values))
print(d)  # 输出:{'name': 'yyy', 'age': '3', 'job': 'programmer'}

(3)通过fromkeys()创建值为空的字典

k = ['name', 'age', 'job']
d = dict.fromkeys(k)
print(d)  # 输出:{'name': None, 'age': None, 'job': None}

小问题:之前说字典的“键”不可重复,如何重复了会怎样?会报错吗?

a = {'name':'yyy', 'age':18, 'age':3}
print(a)  # 输出:{'name': 'yyy', 'age': 3}

可见,如果键重复了,后面的键值对会把前面的覆盖掉。

2.元素的访问

(1)通过[键]获得“值”。

若键不存在,则抛出异常。

a = {'name': 'yyy', 'age': 3, 'job': 'programmer'}
print(a['name'])  # 输出:yyy
print(a['height'])  # 输出:报错:KeyError: 'height'

(2)通过get()方法获得“值”。

**推荐使用!**优点是:指定键不存在,返回None;也可以设定指定键不存在时默认返回的对象。推荐使用get()获取"值对象”。

a = {'name': 'yyy', 'age': 3, 'job': 'programmer'}
print(a.get('name'))  # 输出:yyy# 使用get()不会报错,整个过程变得很优雅~
print(a.get('height'))  # 输出:None# 还尅通过第二个参数指定当键不存在时的返回值
print(a.get('height', 185))  # 输出:185

(3)列出所有的键值对、所有的键、所有的值

a = {'name': 'yyy', 'age': 3, 'job': 'programmer'}b = a.items()
print(b)  # 输出:ict_items([('name', 'yyy'), ('age', 3), ('job', 'programmer')])k = a.keys()
print(k)  # 输出:dict_keys(['name', 'age', 'job'])v = a.values()
print(v)  # 输出:dict_values(['yyy', 3, 'programmer'])

(4)用len()计算键值对的个数

a = {'name': 'yyy', 'age': 3, 'job': 'programmer'}
print(len(a))  # 输出:3

(5)用in检测一个键是否在字典中

a = {'name': 'yyy', 'age': 3, 'job': 'programmer'}
print('name' in a)  # 输出:True
print('height' in a)  # 输出:False

3.元素的添加、修改、删除

(1)给字典新增"键值对"。

如果"键"已经存在,则覆盖旧的键值对;如果"键"不存在,则新增"键值对"。

a = {'name': 'yyy', 'age': 18, 'job': 'programmer'}
a['height'] = 185
a['age'] = 3
print(a)  # 输出:{'name': 'yyy', 'age': 3, 'job': 'programmer', 'height': 185}

(2)使用update()将新字典中所有键值对全部添加到旧字典对象上。

如果key有重复,则直接覆盖

a = {'name': 'yyy', 'age': 3, 'job': 'programmer'}
b = {'name': 'sheep', 'height': 185, 'gender': 'man'}
a.update(b)
print(a)  # 输出:{'name': 'sheep', 'age': 3, 'job': 'programmer', 'height': 185, 'gender': 'man'}

(3)删除元素:del()clear()pop()

字典中元素的删除,可以使用del()方法;或者者clear()删除所有键值对;pop()删除指定键值对,并返回对应的“值对象”。

a = {'name': 'yyy', 'age': 3, 'job': 'programmer', 'height': 185}del(a['name'])
print(a)  # 输出:{'age': 3, 'job': 'programmer', 'height': 185}age = a.pop('age')
print(a)  # 输出:{'job': 'programmer', 'height': 185}
print(age)  # 输出:3a.clear()
print(a)  # 输出:{}

(4)popitem():随机删除和返回该键值对。

字典是"无序可变序列",因此没有第一个元素、最后一个元素的概念;popitem()弹出随机的项,因为字典并没有"最后的元素"或者其他有关顺序的概念。若想一个接一个地移除并处理项,这个方法就非常有效(因为不用首先获取键的列表)

a = {'name': 'yyy', 'age': 3, 'job': 'programmer', 'height': 185}result1 = a.popitem()
result2 = a.popitem()print(result1)  # 输出:('height', 185)
print(result2)  # 输出:('job', 'programmer')
print(a)  # 输出:{'name': 'yyy', 'age': 3}

4.序列解包

序列解包可以用于元组、列表、字典。序列解包可以让我们方便的对多个变量赋值。

x, y, z = (20, 30, 10)
(a, b, c) = (9, 8, 10)
[m, n, p] = ['a', 'b', 'c']

序列解包用于字典时,默认是对"键"进行操作;如果需要对键值对操作,则需要使用items();如果需要对"值"进行操作,则需要使用values();

a = {'name': 'yyy', 'age': 3, 'job': 'programmer'}
x, y, z = a
print(x)  # 输出:namex, y, z = a.items()
print(x)  # 输出:('name', 'yyy')x, y, z = a.values()
print(x)  # 输出:yyy

5.练习:用字典对表格数据进行存取

数据表格如下:

姓名年龄薪资城市
张三1810000北京
李四1930000上海
王五2020000深圳
people1 = {'name': '张三', 'age': 18, 'salary': 10000, 'city': '北京'}
people2 = {'name': '李四', 'age': 19, 'salary': 30000, 'city': '上海'}
people3 = {'name': '王五', 'age': 20, 'salary': 20000, 'city': '深圳'}
# 存进一张表格
table = [people1, people2, people3]
# 访问表格数据
for i in range(len(table)):print(table[i].get('name'), table[i].get('age'), table[i].get('salary'), table[i].get('city'))# 输出:
# 张三 18 10000 北京
# 李四 19 30000 上海
# 王五 20 20000 深圳

三、字典的底层原理(重要)

(1)存储键值对的过程

字典对象的核心是散列表。散列表是一个稀疏数组(总是有空白元素的数组),数组的每个单元叫做bucket。每个bucket有两部分:一个是键对象的引用,一个是值对象的引用。由于,所有bucket结构和大小一致,我们可以通过偏移量来读取指定bucket
在这里插入图片描述
先创建一个字典a:

a = {}a['name'] = 'yyy'

假设字典a对象创建完后,数组长度为8:
在这里插入图片描述
我们要把’name’='yyy’这个键值对放到字典对象a中,首先第一步需要计算键"name"的散列值。Python中可以通过hash()函数来计算。

print(bin(hash('name')))  # 输出:-0b1010111101001110110101100100101

由于数组长度为8,我调拿计算出的散列值的最右边3位数字作为偏移量,即"101",十进制是数字5。我们查看偏移量5,对应的bucket是否为空。如果为空,则将键值对放进去。如果不为空,则依次取右边3位作为偏移量,即"100",十进制是数字4。再查看偏移为4的bucket是否为空。直到找到为空的bucket将键值对放进去。流程图如下:
在这里插入图片描述

那如果当前数组满了怎么办?很简单——扩容
python会根据散列表的拥挤程度扩容。“扩容"指的是:创造更大的数组,将原有内容拷贝到新数组中。接近2/3时,数组就会扩容。

(2)查找值对象的过程

明白了一个键值对是如何存储到数组中的,根据键对象取到值对象,理解起来就简单了。

>>> a.get('name')
'yyy'

当调用a.get('name'),就是根据键’name’查找到"键值对",从而找到值对象’yyy’。我们仍然要首先计算’yyy’对象的散列值:

>>> bin(hash('name'))
'-0b1010111101001110110101100100101'

和存储的底层流程算法一致,也是依次取散列值的不同位置的数字。假设数组长度为8,我们可以拿计算出的散列值的最右边3位数字作为偏移量,即101,十进制是数字5。我们查看偏移量5,对应的 bucket是否为空。如果为空,则返回 None。如果不为空,则将这个bucket的键对象计算对应散列值,和我们的散列值进行比较,如果相等。则将对应"值对象"返回。如果不相等,则再依次取其他几位数字,重新计算偏移量。依次取完后,仍然没有找到。则返回 None。流程图如下:
在这里插入图片描述
在这里插入图片描述


总结

  1. 字典在内存中开销巨大,典型的用空间换时间
  2. 键查询速度很快。
  3. 往字典里面添加新建可能导致扩容,导致散列表中键的次序变化。因此,不要在遍历字典的同时进行字典的修改
  4. 键必须可散列
    • 数字、字符串、元组,都是可散列的
    • 自定义对象需要支持下面三点:(面向对象章节中再展开说)
      ①支持hash()函数
      ②支持通过_eq_()方法检测相等性
      ③ 若a==b为真,则 hash(a)==hash(b)也为真

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/591905.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TDD-LTE TAU流程

目录 1. TAU成功流程 1.1 空闲态TAU 1.2 连接态TAU 2. TAU失败流程 当UE进入一个小区,该小区所属TAI不在UE保存的TAI list内时,UE发起正常TAU流程,分为IDLE和CONNECTED(即切换时)下。如果TAU accept分配了一个新的…

浅析PCIe 6.0功能更新与实现的挑战-5

设备Ready报告机制 Device Readiness Status (DRS) 是PCIe规范中引入的一种机制,旨在改进设备初始化和就绪状态的检测与报告。 在以往的PCIe版本中,系统通常依赖于固定的超时机制来判断设备是否已经成功初始化并准备好进行数据传输。然而,这…

Linux命令和介绍

常见目录介绍 / 根目录 /home/username 普通用户的家目录 /etc 配置文件目录 /bin 命令目录 /sbin 管理命令目录 /usr/bin/sbin 系统预装的其他命令 su - root #切换为root用户 一.万能的帮助命令 1.man 帮助 (manual的缩写) 路径:…

JavaWeb之jQuery

28、jQuery 28.1、jQuery的概述 概念:一个JavaScript框架。简化JS开发 jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨“write Less&#xff0c…

LeetCode每日一题:1154. Day of the Year

文章目录 一、题目二、题解 一、题目 Given a string date representing a Gregorian calendar date formatted as YYYY-MM-DD, return the day number of the year. Example 1: Input: date “2019-01-09” Output: 9 Explanation: Given date is the 9th day of the year…

K8S学习指南(52)-k8s包管理工具Helm

文章目录 引言Helm 基本概念Helm 的架构Helm 使用示例1. 安装 Helm2. 初始化 Helm3. 创建一个 Chart4. 编辑 Chart5. 打包 Chart6. 发布 Chart7. 部署 Release Helm 的高级用法1. 使用 Helm Secrets 进行敏感信息加密2. 使用 Helmfile 进行多Chart管理 Helm 的进阶主题1. Helm …

AI绘图之风景画

这一段时间AI画图比较火,笔者也尝试了一些工具,在使用的过程中发现midjourney比较适合小白,而且画的画比较符合要求。质量也高。当然AI时代的来临大家也不要太慌,毕竟人才是最重要的,AI还是要靠人输入内容才可以生成内…

线程死锁检测组件逻辑与源码

死锁介绍 任务的执行体之间互相持有对方所需的资源而不释放,形成了相互制约而都无法继续执行任务的情况,被称为“死锁”。 死锁案例 线程A持有锁a不释放,需要去获取锁b才能继续执行任务, 线程B持有锁b不释放,需要去…

k8s陈述式资源管理(命令行)

1、资源管理 (1)陈述式资源管理(常用——查、增) 使用kubectl工具进行命令行管理 ①特点:对资源的增删查比较方便,对改不友好 ②优点:90%以上的场景都可以满足 ③缺点:命令冗长…

React Grid Layout基础使用

摘要 React Grid Layout是一个用于在React应用程序中创建可拖拽和可调整大小的网格布局的库。它提供了一个灵活的网格系统,可以帮助开发人员构建响应式的布局,并支持拖拽、调整大小和动画效果。本文将介绍如何使用React Grid Layout来创建自适应的布局。…

canvas绘制圆点示例

查看专栏目录 canvas示例教程100专栏,提供canvas的基础知识,高级动画,相关应用扩展等信息。canvas作为html的一部分,是图像图标地图可视化的一个重要的基础,学好了canvas,在其他的一些应用上将会起到非常重…

如何移除视频中的背景音乐或人物声音

移除视频声音是将视频指定的声音移除,可以选择移除人物声音还是视频的背景音乐,方便实现二次创作。 小编给大家推荐一些方法帮助大家更轻松地移除视频中的背景音乐或人物声音,有兴趣的朋友请自行百度查找,或小程序查找 1、方法&a…

跟我用路由器学Linux编程实例

跟我用路由器学Linux编程实例 本专栏文章以梅林、openwrt等linux路由为基础硬件,和笔者一起学习使用shell语言。带你从编写简单的插件开始,学习怎么折腾路由器,顺便学会编程。软路由用的都是Linux基础系统,学会了在路由上编程&am…

P8722 [蓝桥杯 2020 省 AB3] 日期识别(C语言)

题目描述 小蓝要处理非常多的数据, 其中有一些数据是日期。 在小蓝处理的日期中有两种常用的形式:英文形式和数字形式。 英文形式采用每个月的英文的前三个字母作为月份标识,后面跟两位数字表示日期,月份标识第一个字母大写,后…

2023福建省“信息安全管理与评估“---单机取证(高职组)

2023福建省“信息安全管理与评估“---单机取证(高职组) 2023福建省“信息安全管理与评估“---单机取证(高职组):公众号:鱼影安全(有联系方式)Evidence1:Evidence2:Evidence3:Evidence4:Evidence5:Evidence6:Evidence7:Evidence8:Evidence9:Evidence10:<

从入门到精通,30天带你学会C++【第十四天:洛谷选题讲解】

彩蛋 这么长的目录应该没人看吧。 Bi------------------------------------------------------------------------------- 目录 Everyday English 前言 函数 sqrt ( ) for循环 题目网址 分析题意 思路点拨 优化程序 AC代码 AC截图 数学 if判断 题目网址 思路…

视频剪辑技巧:轻松制作短视频,一键合并、剪辑、添加背景音乐

随着社交媒体的普及&#xff0c;短视频已是分享生活、娱乐和传递信息的重要方式。如果要制作短视频&#xff0c;但又不熟悉复杂的视频编辑软件&#xff0c;那么本文将讲解一些实用的视频剪辑技巧&#xff0c;轻松制作出高质量的短视频。现在一起来看看云炫AI智剪如何批量合并视…

光纤通信系统中常见类型的损伤和均衡方法

相干光纤通信系统中常见的损伤和均衡算法 光纤通信中的系统损伤损耗色度色散 CD偏振相关损耗PMD 偏振模色散RSOP 偏振态旋转PDL 偏振相关损耗 CFO 载波频率偏移和CPN 载波相位噪声 光纤通信系统损伤均衡算法 光纤通信中的系统损伤 信道中常见的损伤包括损耗、色散和偏振相关损…

【HarmonyOS开发】分布式应用的开发实践(元旦快乐)

元旦快乐&#xff0c;再见2023&#xff0c;加油2024&#xff0c;未来可期&#xff0c;愿新的一年带来健康、幸福和成功&#xff01;&#x1f4aa; &#x1f4aa;&#x1f4aa; 多种设备之间能够实现硬件互助、资源共享&#xff0c;依赖的关键技术包括分布式软总线、分布式设备虚…

机器学习基本概念及模型简单代码(自用)

监督学习 监督学习是机器学习的一种方法&#xff0c;其中我们教导模型如何做出预测或决策&#xff0c;通过使用包含输入和对应输出的已标注数据集进行训练。这种方法的关键特点是利用这些标注数据**&#xff08;即带有正确答案的数据&#xff09;**来指导模型的学习过程。 一言…