此文档是Python课程入门篇关于字典的复习文档,本次课程目标是回顾字典的特点及常用操作,并简单了解字典的底层实现原理
复习时间:2024年8月10日
文档总结:2024年8月10日
学习时长:1小时
课程环境:
- win10系统
- Python 3.12.4
- PyCharm Community Edition 2024.1.4
本次课程主要涉及的知识点:
- Python字典的基本概念和特点
- Python字典创建的4种方法
- Python字典中元素的访问
- Python字典中元素的添加、修改、删除
- Python字典中元素删除的3种方法
- Python中序列解包用于字典的3种方法
- Python字典的核心底层原理:内存分析、查找值对象过程(一般了解即可)
阶段复习重点关注:
- Python字典的基本特征,结合其他的几种序列,对比相同点和不同点
- Python字典的应用场景,基本语法
复习过程中的薄弱点与易错点:
- 本阶段暂无
- 注意几种序列的差异和使用场景,需了解序列之间的相同点和不同点
本次课程复习总结:
1、字典的特征总结
特征 | 说明 |
---|---|
字典的形式 | 字典是以“键值对”形式出现的,是无序,可变序列 可以通过“键”对“值进行增删改查 |
键的特征 | 1、键是唯一不能重复的(重复的键对应值会被后面的值覆盖掉) 2、键可以是任意不可变的数据 √ 字符串、元组是不可变的,可以作为键 × 列表、字典、集合是可变对象,不可以作为键 |
值的特征 | 值可以是任意数据,可以重复 |
2、创建字典的常用方法
除了使用{}和dict()创建字典,也结合列表和元组进行字典的创建
字典创建方法 | 创建的基本语法 |
---|---|
通过{}创建 | 字典名 = {"键1":"值1","键2":"值2",…"键n":"值n"} |
通过dict()创建 | 字典名 = dict(键1="值1",键2="值2"…键n="值n") 注意使用dict()中的键都不需要加引号,即便是中文也不加引号,加了会报错 |
通过zip()创建 | 键名 = ["键1","键2",…,"键n"] 字典名 = dict(zip(键名,值名)) |
通过dict.fromkeys([])创建值为None的字典 | 字典名 = dict.fromkeys(["键1","键2",…,"键n"]) 注意键放在列表里,注意不要漏写[] |
3、字典中元素的访问
推荐通过get()方法访问值:如果指定键不存在,返回None,也可以设定指定键不存在时默认返回的对象;
4、字典中元素的更新
字典更新的2种办法:
- 方法1:字典名[key]=value
- 方法2:需要更新的字典1.update(更新的值所在字典2)
本阶段练习题:
第一部分:字典的创建
1、创建字典的几种方法
# 方式1:通过{}创建
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
print(stu1)
个人易错点提示:通过dict()创建字典时,经常把dict()写成dic()
# 方式2:通过dict()创建
# 个人易错点提示:创建字典时,经常把dict()写成dic()
stu2 = dict(sid = 2,sname = "张无忌",sex = "男",age = 20)
print(stu2)
# 通过dict()创建字典也可以写成以下形式
stu21 = dict([("sid",21),("sname","张无忌"),("sex","男"),("age",20)])
print(stu21)
一个不重要的提示:在使用dict()创建字典时,键可以是中文,但注意中文同样不需要加引号
- 个人易错点提示:遇到中文习惯性加"",注意这里可以用中文,但是不需要加引号
- 可以把这个过程理解为“把值赋给键”(更准确地说,是在创建一个字典时,通过键值对的方式来初始化字典中的元素)
stu2 = dict(学号 = 2,姓名 = "张无忌",性别 = "男",年龄 = 20)
# 返回值是:{'学号': 2, '姓名': '张无忌', '性别': '男', '年龄': 20}
print(stu2)
# 方式3:通过zip()创建
k = ["sid","sname","sex","age"]
v = [3,"张无忌","男",20]
# 注意直接用zip()返回的是一个可迭代对象
# stu3 = zip(k,v) # <zip object at 0x00000290B595F400>
stu3 = dict(zip(k,v))
print(stu3)
个人易错点提示:通过fromkeys创建字典时,会dict([])漏写列表[] 导致报错
# 方式4:通过fromkeys创建值为空的字典
# 个人易错点提示:通过fromkeys创建字典时,会dict([])漏写列表[]
stu_key = dict.fromkeys(["sid","sname","sex","sage"])
# 返回的是:{'sid': None, 'sname': None, 'sex': None, 'sage': None}
print(stu_key)
创建字典的一个注意点:当键重复时,前面的键对应的值会被后面覆盖
# 创建字典的一个注意点:当键重复时,前面的键值会被后面覆盖
stu_ks = {"sid":1,"sname":"张无忌","sex":"男","age":20,"age":99}
# 返回的是:{'sid': 1, 'sname': '张无忌', 'sex': '男', 'age': 99},第一个age:20被覆盖了
print(stu_ks)
第二部分:字典元素的访问
设定用于测试各种方法的字典为:
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
1、列出字典中所有的键值对,使用items()方法
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 列出字典中所有的键值对,使用items()方法
stu_kv = stu1.items()
# 返回值是:dict_items([('sid', 1), ('sname', '张无忌'), ('sex', '男'), ('age', 20)])
print(stu_kv)
2、列出字典中所有的键,使用keys()方法
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 列出字典中所有的键,使用keys()方法
stu_keys = stu1.keys()
# 返回值是:dict_keys(['sid', 'sname', 'sex', 'age'])
print(stu_keys)
3、列出字典中所有的值,使用values()方法
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 列出字典中所有的值,使用values()方法
stu_values = stu1.values()
# 返回值是:dict_values([1, '张无忌', '男', 20])
print(stu_values)
4、列出字典中键值对的个数,使用len()方法
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 获取字典中键值对的个数,使用len()方法
stu_len = len(stu1)
print(stu_len)
5、检测一个键是否在字典中存在,使用in;返回值是True/False
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 检测一个键是否在字典中存在,使用in,返回值是True/False
print("sname" in stu1) # "sname"是字典stu1中的键,返回 True
print("sgender" in stu1) # "sgender"不是字典stu1中的键,返回 False
6、字典中值的访问
通过键访问值
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 方式1:通过键访问值
sname1 = stu1["sname"]
# 此种方法在访问的键不存在的情况下会报错:KeyError
# s1 = stu1["sgender"] # 报错:KeyError: 'sgender'
print(sname1)
通过get()方法访问值
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 方式2:通过get()方法访问值
sid1 = stu1.get("sid")
print(sid1)
# 指定键不存在,返回None
sbirth1 = stu1.get("sbirth1")
# 返回None
print(sbirth1)
# 可以设定指定键不存在时默认返回的对象
sgender1 = stu1.get("sgender","男")
# sgender不是字典中存在的键,返回默认值"男"
print(sgender1)
第三部分:字典元素的添加、修改、删除
设定用于测试各种方法的字典为:
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
1、给字典新增“键值对”
新增不重复的键,会增加一组新的键值对;新增重复的键,会覆盖原来的值;
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 给字典新增“键值对”
# 方式1:新增不重复的键,会直接增加一组新的键值对
stu1["scity"] = "南京" # {'sid': 1, 'sname': '张无忌', 'sex': '男', 'age': 20, 'scity': '南京'}
print(stu1)
# 方式2:新增重复的键,会覆盖原来的值
stu1["age"] = 23 # {'sid': 1, 'sname': '张无忌', 'sex': '男', 'age': 23, 'scity': '南京'}
print(stu1)
2、更新字典的键值对,和新增类似,没有重复就增加,key有重复会覆盖原本的value
# 更新字典的键值对,和新增类似,没有重复就增加,key有重复会覆盖原本的value
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
stu2 = {"sid":2,"sname":"孙悟空","age":600,"scity":"北京"}
"""
把a.update(b)括号中b的值更新到字典a中
1、如果b中的key不在a中,则在a中增加一个key:新增了一个"scity"的键
2、如果b中的key和a中的重复,则覆盖a的value:"age"键重复,值被覆盖为600
3、如果a中的key不在b的key里,a中的key不会被删除:"sex"键没有删除,仍然保留
"""
stu1.update(stu2)
# 返回的值:{'sid': 2, 'sname': '孙悟空', 'sex': '男', 'age': 600, 'scity': '北京'}
print(stu1)
3、字典中元素的删除
del()方法删除指定的键值对,没有返回值
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 方法1:del()方法删除指定的键值对,没有返回值
del(stu1["sex"])
# 返回的值:{'sid': 1, 'sname': '张无忌', 'age': 20}
print(stu1)
pop()方法删除指定的键值对,可以返回对应的值对象
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 方法2:pop()方法删除指定的键值对,可以返回对应的值对象
sex = stu1.pop("sex")
print(sex) # 返回的值:男
# 返回的值:{'sid': 1, 'sname': '张无忌', 'age': 20}
print(stu1)
个人易错点提示:通过pop()删除键值对时,由于先删除了key,不能再返回对应的值,报错KeyError: 'sex'
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
"""
这是错误的写法,key已经被删除了,后面再执行没有返回值会报错:KeyError: 'sex'
"""
stu1.pop("sex") # 这里删除之后,后面就没有返回值了
sex = stu1.pop("sex") # KeyError: 'sex'
print(sex)
print(stu1)
clear()方法删除所有的键值对,返回的是一个空字典
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 方法3:clear()方法删除所有的键值对,返回的是一个空字典
stu1.clear()
print(stu1) # 返回空字典{}
popitem()方法随机删除和返回该键值对
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 方法4:popitem()方法随机删除和返回该键值对
p1 = stu1.popitem()
p2 = stu1.popitem()
p3 = stu1.popitem()
p4 = stu1.popitem() # 本次随机删除之后,stu1是一个空字典{}
# 随机删除次数超过键值对格式之后会报错:KeyError: 'popitem(): dictionary is empty'
# p5 = stu1.popitem() # 这一步无法继续执行,因为空列表没有键值对可删除了
print(stu1)
# 若想一个接一个地移除并处理项,这个方法就非常有效(因为不用首先获取键的列表)
- 字典是“无序可变序列”,不存在第一个元素、最后一个元素
- popitem()方法删除的项是随机的,没有“第一”、“最后”等有关顺序的概念
- 若想一个接一个地移除并处理项,使用popitem()方法非常有效,因为不用首先获取键的列表
第四部分:字典的其他操作
1、序列解包用于字典
序列解包用于字典时,默认是对“键”进行操作
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 序列解包1:默认是对键操作,keys()是默认方法,可以省略不写
k1,k2,k3,k4 = stu1 #这里可以写成:k1,k2,k3,k4 = stu1.keys()
# 相当于:把字典中的键取出来,用4个变量来接收
"""
注意这里的变量数量要和字典中的键保持一致,否则会报错
太少报错 ValueError: too many values to unpack (expected 3)
太多也报错 ValueError: not enough values to unpack (expected 5, got 4)
"""
print(k1) # 返回的值:sid # 再次强调,字典是无序的,不存在第一最后的概念
序列解包可以用items()对键值进行操作
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 序列解包2:用items()对键值进行操作
kv1,kv2,kv3,kv4 = stu1.items()
print(kv1) # 返回的是一个元组:('sid', 1)
序列解包可以用values()对值进行操作
stu1 = {"sid":1,"sname":"张无忌","sex":"男","age":20}
# 序列解包3:用values()对值进行操作
v1,v2,v3,v4 = stu1.values()
print(v1) # 返回的值:1
第五部分:字典的综合练习
1、创建一个字典对象,包含如下信息:支出金额:300.15,支出日期:2018.10.18,支出人:高小七
# 方法1:通过{}创建
dic1 ={"支出金额":300.15,"支出日期":"2018.10,18","支出人":"高小七"}
print("方法1:通过{}创建",dic1)
# 方法2:通过dict()创建
dic2 = dict(支出金额=300.15,支出日期="2018.10,18",支出人="高小七")
print("方法2:通过dict()创建",dic2)
dic21 = dict([("支出金额",300.15),("支出日期","2018.10,18"),("支出人","高小七")])
print("方法21:通过dict()创建",dic21)
# 方法3:通过zip()创建
k = ["支出金额","支出日期","支出人"]
v = [300.15,"2018.10,18","高小七"]
dic3 = dict(zip(k,v))
print("方法3:通过zip()创建",dic3)
# 方法4.1 通过fromkeys()创建空值字典,然后通过键值对覆盖更新字典的值
dic4 = dict.fromkeys(["支出金额","支出日期","支出人"])
dic4["支出日期"]=300.15
dic4["支出日期"]="2018.10.18"
dic4["支出人"]="高小七"
print("方法4.1 通过键值对覆盖更新字典的值",dic4)
# 方法4.2 通过fromkeys()创建空值字典,然后通过update()更新
dic4 = dict.fromkeys(["支出金额","支出日期","支出人"])
dic42 = {"支出金额":300.15,"支出日期":"2018.10,18","支出人":"高小七"}
dic4.update(dic42)
print("方法4.2 使用update()更新",dic4)
2、 找出下面这个字典对象dic中值最大的那个键,dic = {"a": 1,"b": 2,"c": 3}
# 找出下面这个字典对象dic中值最大的那个键,dic = {"a": 1,"b": 2,"c": 3}
dic = {"a": 1,"b": 2,"c": 3}
v_max = max(dic,key = lambda x:dic[x])
print(v_max)
3、将字典对象d2中的a、b键的值互换,d2 = {'a': 1, 'b': 2}
# 将字典对象d2中的a、b键的值互换,d2 = {'a': 1, 'b': 2}
d2 = {'a': 1, 'b': 2}
d2['a']=2
d2['b']=1
print(d2)
第六部分:其他补充的知识(日常工作不用,考试可能会用到,不需要深入了解)
字典的核心底层原理:内存分析、查找值对象过程
字典(Dictionary)在计算机科学中是一种常见的数据结构,也被称为映射(Map)或关联数组(Associative Array)。它主要用于存储键值对(Key-Value Pair),其中每个键都唯一地映射到一个值。
字典的核心底层原理主要基于哈希表(Hash Table)的实现,以下是字典核心底层原理的详细解析:
1. 哈希表基础
- 哈希函数:哈希函数是字典实现的核心。它能够将任意长度的输入(键)通过某种算法变换成固定长度的输出,即哈希值(Hash Value)。哈希函数的目的是减少冲突,即将不同的键映射到不同的哈希值上,从而提高查找效率。
- 哈希表:哈希表是一个通过哈希函数组织起来的数组,用于存储键值对。数组的每个元素被称为桶(Bucket),每个桶中存放一个链表或其他数据结构,以处理哈希冲突。
2. 存储过程
- 当插入一个键值对时,首先通过哈希函数计算键的哈希值。
- 根据哈希值确定键应该存放在哈希表中的哪个桶中(通常是通过哈希值对数组长度取模得到桶的索引)。
- 如果该桶已经包含其他键值对(即发生了哈希冲突),则采用某种冲突解决方法(如开放地址法、拉链法等)来处理。
- 将键值对添加到桶所指向的数据结构中(如链表末尾)。
3. 查找过程
- 当要查找某个键对应的值时,首先通过哈希函数计算该键的哈希值。
- 根据哈希值定位到哈希表中的对应桶。
- 在桶所指向的数据结构中查找对应的键值对。
- 如果找到了匹配的键,则返回对应的值;否则,返回未找到的结果。
4. 字典的特点
- 唯一性:每个键在字典中必须是唯一的,不能有重复的键。
- 无序性:字典中的键值对通常是无序的,即它们的存储顺序并不重要。
- 高效性:由于哈希表的特性,字典的查找、插入和删除操作通常具有很高的效率,接近常数时间复杂度。
5. 扩容与重哈希
- 当哈希表中的元素数量增加到一定程度时(如达到某个阈值,如装载因子接近2/3),为了保持哈希表的性能,需要进行扩容操作。
- 扩容时,会创建一个更大的哈希表,并将原有哈希表中的所有键值对重新通过哈希函数映射到新的哈希表中。
综上所述,字典的核心底层原理是基于哈希表的实现,通过哈希函数和哈希表来高效地组织和管理键值对数据。这种实现方式使得字典在查找、插入和删除操作上具有很高的性能。
参考 视频教程: 【尚学堂】Python基础400集>>第三章 序列>>字典_核心底层原理_内存分析_存储键值对过程 CSDN文章: Python字典_核心底层原理_内存分析_存储与查找键值对过程: https://blog.csdn.net/manba_yqq/article/details/136263900 参考站外链接: 字典的原理是什么: https://linuxcpp.0voice.com/?id=192928 深入底层了解Python字典和集合,一眼看穿他们的本质: https://c.biancheng.net/view/vip_6003.html 基于文心大模型,版本:V3.1.0