Skip to content

Latest commit

 

History

History
316 lines (203 loc) · 9.52 KB

Dict.md

File metadata and controls

316 lines (203 loc) · 9.52 KB

一、字典(Dictionary)

1、什么是 dict(字典)

上一章节,我们学习了列表(List) 和 元组(tuple) 来表示有序集合。

而我们在讲列表(list)的时候,我们用了列表(list) 来存储用户的姓名。

name = ['一点水', '两点水', '三点水', '四点水', '五点水']

那么如果我们为了方便联系这些童鞋,要把电话号码也添加进去,该怎么做呢?

用 list 可以这样子解决:

name = [['一点水', '131456780001'], ['两点水', '131456780002'], ['三点水', '131456780003'], ['四点水', '131456780004'], ['五点水', '131456780005']]

但是这样很不方便,我们把电话号码记录下来,就是为了有什么事能及时联系上这些童鞋。

如果用列表来存储这些,列表越长,我们查找起来耗时就越长。

这时候就可以用 dict (字典)来表示了,Python 内置了 字典(dict),dict 全称 dictionary,如果学过 Java ,字典就相当于 JAVA 中的 map,使用键-值(key-value)存储,具有极快的查找速度。

name = {'一点水': '131456780001', '两点水': '131456780002', '三点水': '131456780003', '四点水': '131456780004', '五点水': '131456780005'}

2、dict (字典)的创建

字典是另一种可变容器模型,且可存储任意类型对象。

字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中 ,格式如下所示:

dict = {key1 : value1, key2 : value2 }

注意:键必须是唯一的,但值则不必。值可以取任何数据类型,但键必须是不可变的。

更准确地说,字典的键必须可哈希。包含列表的元组虽然自身不可变,也不能作为字典键;不能只根据「可变/不可变」判断。

创建 dict(字典)实例:

dict1={'liangdianshui':'111111' ,'twowater':'222222' ,'两点水':'333333'}
dict2={'abc':1234,1234:'abc'}

3、访问 dict (字典)

我们知道了怎么创建列表了,回归到一开始提出到的问题,为什么使用字典能让我们很快的找出某个童鞋的电话呢?

name = {'一点水': '131456780001', '两点水': '131456780002', '三点水': '131456780003', '四点水': '131456780004', '五点水': '131456780005'}

print(name['两点水'])

输出的结果:

131456780002

可以看到,如果你知道某个人的名字,也就是 key 值, 就能很快的查找到他对应的电话号码,也就是 Value 。

这里需要注意的一点是:如果字典中没有这个键,是会报错的。

4、修改 dict (字典)

向字典添加新内容的方法是增加新的键/值对,修改或删除已有键/值对

#-*-coding:utf-8-*-
dict1={'liangdianshui':'111111' ,'twowater':'222222' ,'两点水':'333333'}
print(dict1)
# 新增一个键值对
dict1['jack']='444444'
print(dict1)
# 修改键值对
dict1['liangdianshui']='555555'
print(dict1)

输出的结果:

{'liangdianshui': '111111', 'twowater': '222222', '两点水': '333333'}
{'liangdianshui': '111111', 'twowater': '222222', '两点水': '333333', 'jack': '444444'}
{'liangdianshui': '555555', 'twowater': '222222', '两点水': '333333', 'jack': '444444'}

5、删除 dict (字典)

通过 del 可以删除 dict (字典)中的某个元素,也能删除 dict (字典)

通过调用 clear() 方法可以清除字典中的所有元素

#-*-coding:utf-8-*-
dict1={'liangdianshui':'111111' ,'twowater':'222222' ,'两点水':'333333'}
print(dict1)
# 通过 key 值,删除对应的元素
del dict1['twowater']
print(dict1)
# 删除字典中的所有元素
dict1.clear()
print(dict1)
# 删除字典
del dict1

输出的结果:

{'liangdianshui': '111111', 'twowater': '222222', '两点水': '333333'}
{'liangdianshui': '111111', '两点水': '333333'}
{}

6、 dict (字典)使用时注意的事项

(1) dict (字典)是不允许一个键创建两次的,但是在创建 dict (字典)的时候如果出现了一个键值赋予了两次,会以最后一次赋予的值为准

例如:

#-*-coding:utf-8-*-
dict1={'liangdianshui':'111111' ,'twowater':'222222' ,'两点水':'333333','twowater':'444444'}
print(dict1)
print(dict1['twowater'])

输出的结果:

{'liangdianshui': '111111', 'twowater': '444444', '两点水': '333333'}
444444

(2) dict (字典)键必须不可变,可是键可以用数字,字符串或元组充当,但是就是不能使用列表

例如:

#-*-coding:utf-8-*-
dict1={'liangdianshui':'111111' ,123:'222222' ,(123,'tom'):'333333','twowater':'444444'}
print(dict1)

输出结果:

{'liangdianshui': '111111', 123: '222222', (123, 'tom'): '333333', 'twowater': '444444'}

(3) dict 内部存放的顺序和 key 放入的顺序是没有任何关系

和 list 比较,dict 有以下几个特点:

  • 查找和插入的速度极快,不会随着key的增加而变慢

  • 需要占用大量的内存,内存浪费多

而list相反:

  • 查找和插入的时间随着元素的增加而增加

  • 占用空间小,浪费内存很少

7、dict (字典) 的函数和方法

方法和函数 描述
len(dict) 计算字典元素个数
str(dict) 输出字典可打印的字符串表示
type(variable) 返回输入的变量类型,如果变量是字典就返回字典类型
dict.clear() 删除字典内所有元素
dict.copy() 返回一个字典的浅复制
dict.values() 返回由字典中所有值组成的视图,可以用 for 遍历
popitem() 返回并删除最后加入的一对键和值
dict.items() 返回由 (键, 值) 元组组成的视图,可以用 for 遍历

8、Python 3.9+ 的新写法:dict 合并运算符

各位童鞋,前面咱们讲了 dict 的增、删、改、查。这里再补一个 Python 3.9 之后才出现的好东西—— dict 合并运算符 | 和 |= 。

为什么要专门讲它啊?

我们先来看一个需求,假设水哥手上有两份联系人字典,需要把它们合并成一份:

old_contacts = {'一点水': '131456780001', '两点水': '131456780002'}
new_contacts = {'三点水': '131456780003', '两点水': '131456780099'}

注意上面,水哥 这个 key 在两份里都有,我们希望以「新的」为准。

在 Python 3.9 之前,常见的写法是这样:

old_contacts = {'一点水': '131456780001', '两点水': '131456780002'}
new_contacts = {'三点水': '131456780003', '两点水': '131456780099'}

merged = {**old_contacts, **new_contacts}
print(merged)

输出的结果:

{'一点水': '131456780001', '两点水': '131456780099', '三点水': '131456780003'}

这种 ** 解包写法没毛病,但是不够直观。 Python 3.9 之后,可以直接用 | :

old_contacts = {'一点水': '131456780001', '两点水': '131456780002'}
new_contacts = {'三点水': '131456780003', '两点水': '131456780099'}

merged = old_contacts | new_contacts
print(merged)

输出的结果:

{'一点水': '131456780001', '两点水': '131456780099', '三点水': '131456780003'}

是不是发现,跟 set 的并集 | 长得一模一样?没错,作者就是这个意思——「把两个 dict 合并起来」。

如果你不想生成新字典,而是直接「在原字典上」合并新内容,那就用 |= :

old_contacts = {'一点水': '131456780001', '两点水': '131456780002'}
new_contacts = {'三点水': '131456780003', '两点水': '131456780099'}

old_contacts |= new_contacts
print(old_contacts)

输出的结果:

{'一点水': '131456780001', '两点水': '131456780099', '三点水': '131456780003'}

注意,| 是「右边覆盖左边」,跟 {**a, **b} 的逻辑一致。各位用的时候要留意这一点,别把哪边是新的、哪边是旧的搞反了。

最后,再啰嗦一个之前没有强调的点:从 Python 3.7 开始,dict 已经「保留插入顺序」了。也就是说,前面讲的「dict 内部存放的顺序和 key 放入的顺序是没有任何关系」这条结论,在现代 Python 里其实已经不成立了。看看这个例子:

d = {}
d['c'] = 3
d['a'] = 1
d['b'] = 2

for key in d:
    print(key)

输出的结果:

c
a
b

是不是发现,遍历的顺序就是当初插入的顺序?这是 Python 3.7+ 的语言级保证(之前 3.6 已经是 CPython 的实现细节,但没写进规范)。所以现在大多数情况下,你不再需要专门去 import collections.OrderedDict 了,普通的 dict 就够用。

同一个科目再学一次,记录怎么更新

我们已经记下 Python 学了 15 分钟、读书用了 10 分钟。如果又学了 5 分钟 Python,是新增一个相同的键,还是修改原来的值呢?

totals = {'Python': 15, '读书': 10}
totals['Python'] = totals['Python'] + 5
print(totals)
print(totals.get('数学', 0))

输出:

{'Python': 20, '读书': 10}
0

同一个字典中,一个键只能对应一个值。赋值前先取出原来的 15,加上 5,再存回去,所以 Python 的累计时间变成了 20。get('数学', 0) 则表示:如果没有这个科目,就返回我们给出的默认值 0,不会因此增加一个新键。

各位自己试一下:把右边改成直接赋值 5,结果有什么不同?再给字典加上一个新科目,观察已有记录是否还在。学到循环以后,我们再来处理很多条学习记录。