字典是python的内置基本数据类型之一,其他语言中可能会被称为“关联存储”或“关联数组”。它是一种映射关系,以包含在{}中的"键:值"对表示。字典是一种可变对象,键没有顺序。其主要用途是通过关键字存储、提取值。
目录
一、字典的创建
1.1 常量方式创建
1.2 使用类构造器dict创建
1.3 使用字典推导式创建
二、常用字典方法
三、常见字典应用
3.1 有序字典
3.1.1 使用列表的sort方法
3.1.2 使用sorted函数
3.1.3 使用collections.OrderedDict容器数据类型
3.2 多值字典
3.2.1 使用容器类型作为值
3.2.2 使用collections.defaultdict容器数据类型
3.3 键值反转
一、字典的创建
字典有很多种创建方式,你可以直接以常量方式编写,或使用类构造器或字典推导式来创建字典。
1.1 常量方式创建
字典是以{}包围的键值对,键和值以冒号分隔,键值对之间以逗号分隔,按这种格式可以直接编写出字典。
直接输入{}就初始化了一个空字典:
d = {}
type(d)
创建字典的同时输入键值:
d = {'Vincent':1, 'Victor':2, 'Grace':3}
type(d)
python中的另一种数据结构集合(Set)也是包含在{}中的,集合是唯一不可变对象的无序集合,但{}创建的是空字典,空集合必须要用set函数来创建。
s = set(['a', 'b', 'a'])
- 创建集合过程中,重复值"a"只保留一个,集合可以看作是没有值的字典。
1.2 使用类构造器dict创建
类构造器dict也可以创建字典,且兼容的输入形式更多。
直接调用dict()即初始化了一个空字典:
d = dict()
type(d)
可以用多种形式给dict()提供键值对,如:key=value, [(key, value) …] , zip()等,下面4种方式创建出来的字典是一样的:
d1 = dict(Vincent=1, Victor=2, Grace=3)
d2 = dict( [('Vincent', 1), ('Victor', 2), ('Grace', 3)] )
d3 = dict( zip(['Vincent', 'Victor', 'Grace'], [1, 2 ,3]) )
d4 = dict( {'Vincent':1, 'Victor':2}, Grace=3 )
- 注意用第一种方式key=value,键是没有引号的。
1.3 使用字典推导式创建
字典推导式和列表与集合的推导式类似,它包含在{}中,需要以冒号分隔的2个变量,后面跟上for和if子句(if子句可省略),推导式会执行for循环将求得的值依次加入字典。
求10以内偶数的2次幂,并保存到字典中:
d = {x:x**2 for x in range(10) if x%2==0}
- range(10)返回0~9共10个数字,for会在这10个数中循环,判断if条件,满足的则计算并加入字典中
字典推导式另一个常见的用法是从其他字典中筛选子集,例如从d1中筛选value小于3的记录,保存一个子集:
d1 = dict(Vincent=1, Victor=2, Grace=3)
d5 = {k:v for k,v in d1.items() if v<3} # 字典推导式
d5
二、常用字典方法
字典提供了非常丰富的方法,部分常用的如下(d代表字典对象):
- d.keys(),d.values(),d.items() 分别返回由键、值、(键, 值)组成的可迭代对象,可以遍历字典的键,值,和键值对
- d[key] 返回d中键为key的值,如果key不存在,则会引发KeyError。也可以用于字典赋值。
- key in d 测试键key是否在d中,存在返回True,否则返回False
- list(d) 返回d中所有键组成的列表
- len(d) 返回d中项目数,一个键值对算一项
- d.get(key [, default]) 如果key存在则返回key的值,否则返回default,常用在累加统计场景,可以避免KeyError异常
- d.pop(key [, default]) 如果key存在则移除并返回key的值,否则返回default,适用于字典的消耗性迭代
- d.popitem() 从字典中移除并返回一个(键, 值)组成的元组,键值对会按LIFO的顺序返回,适用于字典的消耗性迭代
通过d.keys()遍历字典键,并使用d[key]获取键对应的值:
for k in d1.keys():
print(k,'=>' ,d1[k])
- 由于字典本身就是一个可迭代对象,因此keys()可以省略,for k in d1.keys(): 可以直接写成 for k in d1:
上面的示例也可用d.items()改写为,items()会以元组的方式返回键值对,需要2个参数:
for k,v in d1.items():
print(k, '=>', v)
get(key [, default]) 可以在key不存在时可以返回默认值而不是引发KeyError,这个特点非常适合用在统计场景,例如统计文章中每个单词出现的次数(这里用一句话代替):
str = "How Many Cookies Could a Good Cook Cook if a Good Cook Could Cook Cookies?"
l = str.split(' ') # 用空格拆分单词,得到单词的列表,这里没有去除标点
d = {} # 构造一个空字典,用于存储单词及计数
for word in l:
d[word] = d.get(word, 0) + 1
- d.get(word, 0) 在键word首次出现(即键不存在时),不会引发KeyError,而是会返回0,同时通过d[word]赋值将该键加到字典中
- d[word] = d.get(word, 0) + 1,方法d.get(word, 0)在获取d[word]的值后,加1后又赋值回去,实现单词的累加统计。
d.pop(key [, default])和d.popitem() 是消耗性迭代,一个返回值,一个返回键值对组成的元组,用法类似。
三、常见字典应用
字典的应用场景非常广泛,变化也非常多,下面介绍排序,多值映射,键值反转场景。
3.1 有序字典
Python原生的字典对象是无序的,如果我们确实需要强调某种顺序的时候,可以使用某些方法来使字典保持有序。
3.1.1 使用列表的sort方法
一个常用的方法就是通过列表来进行间接排序(列表是有序的)。例如需要按键排序,可以先将字典键收集到列表中,使用列表的sort方法对键值排序,然后使用for循环遍历显示结果。
d = dict(d=4, b=2, a=1, c=3)
ks = list(d.keys())
ks.sort()
for key in ks:
print(key, '=>', d[key])
3.1.2 使用sorted函数
也使用sorted内置函数一步完成,sorted()函数会对可迭代对象排序,并返回一个列表。由于字典本身就是可迭代对象,因此sorted(d)会直接返回排序后的键列表,我们直接遍历即可:
d = dict(d=4, b=2, a=1, c=3)
for key in sorted(d, reverse=True):
print(key, '=>', d[key])
- 这里用了reverse=True定义降序遍历,如果要升序遍历,省略reverse关键字即可。
3.1.3 使用collections.OrderedDict容器数据类型
上面两种方法都是借助了其他有序的数据类型,在遍历字典时实现间接排序,如果想要字典本身保持有序,可以借助python标准库中的collections.OrderedDict。
这是dict的一个字类,可以用于构造有序字典。有序字典被设计用在强调排序的场景,例如在构造JSON这种需要保持顺序的数据时非常有用,其在效率上不如常规字典(有序字典内部会额外维护双向链表来保持元素顺序)。
有序字典构造方法和dict一样,但OrderedDict()会根据元素加入顺序来排列键值对:
from collections import OrderedDict
d = OrderedDict(a=1, b=2, c=3)
d
OrderedDict也可以通过popitem()方法来返回并移除一个键值对,默认按LIFO先进后出方式从尾部返回键值对:
d.popitem()
通过参数last=False使用FIFO先进先出的方式从头部返回键值对:
d.popitem(last=False)
有序字典通过move_to_end(key [,last=True])方法还可以将指定元素移动到开头或结尾,默认将指定键值对移动到字典的结尾:
d.move_to_end('a')
如果last参数被设置为False,则会移动开头:
d.move_to_end('c', last=False)
3.2 多值字典
通常情况下,键和值是一对一的关系。如果要实现一个键对应多个值,我们需要将多个值包装成一个整体(放入其他容器类型中)作为值。
3.2.1 使用容器类型作为值
我们可以将多个值放在其他容器类型中(列表/集合等),以一个整体作为值,如果需要保持多个值的顺序就用列表,需要保持值唯一就用集合:
d1= dict(a=[1,2,1], b=[4,5,6], c=[7,7,7])
d2= dict(a={1,2,1}, b={4,5,6}, c={7,7,7})
由于值是列表类型,可以使用列表的方法来修改值:
d1['a']
d1['a'].append(4)
d1['a']
上面的示例是采用常量的方法将值编写为列表/集合的容器类型,但对于不存在的键,其值类型是未知的,无法直接调用列表/集合方法来添加值:
d1['x'].append(1) # 报错
你需要先初始化值的类型,才能调用相应的方法:
d1['x'] = []
d1['x'].append(1)
3.2.2 使用collections.defaultdict容器数据类型
python的标准库提供了collections.defaultdict()来帮助你更方便的建立多值字典,其在初始化时可以指定值的容器类型。即默认的dict()构造的是"键-值"对,而collections.defaultdict(list)可以构造"键-列表"对或collections.defaultdict(set)构造"键-集合"对。
例如,构造一个键-列表对,对于值可以对值直接调用列表方法:
from collections import defaultdict
d3 = defaultdict(list)
d3['x'].append(1)
或构造一个键-集合对,方式也一样:
d4 = defaultdict(set)
d4['y'].add(1)
通过使用defaultdict,可以省去每次新增一个键,都要显式声明其值的容器类型的操作。
3.3 键值反转
字典的反转键值只需要分别将键(d.keys())和值(d.values())提取出来,通过zip函数构造出"值-键"对,即可实现键-值反转。
zip函数会在多个可迭代对象上并行迭代,并从每个迭代对象返回一个元素组成元组,例如:
z = zip(['a','b','c'], [1,2,3])
z
zip函数返回的也是一个可迭代对象,可以通过for循环进行遍历:
for k in z: print(k)
注意可迭代对象是消耗性的,遍历一次后就没了,如果要再次使用,需要使用zip函数重新构造:
for k in z: print(k)
- 第二次遍历,发现z空了
了解了zip函数的功能,可以很方便通过d.keys(), d.values()和zip函数构造出一个键值反转的字典:
d5 = dict(a=1, b=2, c=3)
d5_reversed = dict(zip(d5.values(),d5.keys())) # d5.values()在前,d5.keys()在后
d5_reversed
其他的方面的字典应用,如求交集,差集,最大值,最小值等,大多数都是围绕d.keys(), d.values(), d.items()这3个函数做文章,大家可以自行尝试。