Python 字典(dict)
是一种无序的、可变的序列,它的元素以“键值对(key-value)
”的形式存储。相对地,列表(list)
和元组(tuple)
都是有序的序列,它们的元素在底层是挨着存放的。
字典类型是 Python 中唯一的映射类型。
“映射”是数学中的术语,简单理解,它指的是元素之间相互对应的关系,即通过一个元素,可以唯一找到另一个元素。
字典中,习惯将各元素对应的索引称为键(key),各个键对应的元素称为值(value),键及其关联的值称为“键值对
”。
字典类型
很像新华字典。
我们知道,通过新华字典中的音节表,可以快速找到想要查找的汉字。其中,字典里的音节表就相当于字典类型中的键,而键对应的汉字则相当于值。
总的来说,字典类型所具有的主要特征如下所示。
主要特征 | 解释 |
---|---|
通过键而不是通过索引来读取元素 | 字典类型有时也称为关联数组或者散列表(hash)。它是通过键将一系列的值联系起来的,这样就可以通过键从字典中获取指定项,但不能通过索引来获取。 |
字典是任意数据类型的无序集合 | 和列表、元组不同,通常会将索引值 0 对应的元素称为第一个元素,而字典中的元素是无序的。 |
字典是可变的,并且可以任意嵌套 | 字典可以在原处增长或者缩短(无需生成一个副本),并且它支持任意深度的嵌套,即字典存储的值也可以是列表或其它的字典。 |
字典中的键必须唯一 | 字典中,不支持同一个键出现多次,否则只会保留最后一个键值对。 |
字典中的键必须不可变 | 字典中每个键值对的键是不可变的,只能使用数字、字符串或者元组,不能使用列表。 |
Python 中的字典类型相当于 Java 或者 C++ 中的 Map 对象。
和列表、元组一样,字典也有它自己的类型。Python 中,字典的数据类型为 dict
,通过 type() 函数即可查看:
>>> a = {'one': 1, 'two': 2, 'three': 3} #a是一个字典类型 >>> type(a) <class 'dict'>
由于字典中每个元素都包含两部分,分别是键(key)
和值(value)
,因此在创建字典时,键和值之间使用冒号:
分隔,相邻元素之间使用逗号,
分隔,所有元素放在大括号{ }
中。
使用{ }
创建字典的语法格式如下:
dictname = {'key':'value1', 'key2':'value2', ..., 'keyn':valuen}
其中 dictname 表示字典变量名,keyn : valuen
表示各个元素的键值对。需要注意的是,同一字典中的各个键必须唯一,不能重复。
#使用字符串作为key scores = {'数学': 95, '英语': 92, '语文': 84} print(scores) 输出:{'数学': 95, '英语': 92, '语文': 84} #使用元组和数字作为key dict1 = {(20, 30): 'great', 30: [1,2,3]} print(dict1) 输出:{(20, 30): 'great', 30: [1, 2, 3]} #创建空元组 dict2 = {} print(dict2) 输出:{}
可以看到,字典的键可以是整数、字符串或者元组,只要符合唯一和不可变的特性就行;字典的值可以是 Python 支持的任意数据类型。
Python 中,还可以使用 dict 字典类型提供的 fromkeys()
方法创建带有默认值的字典,具体格式为:
dictname = dict.fromkeys(list,value=None)
其中,list 参数
表示字典中所有键的列表(list)
;value 参数表示默认值,如果不写,则为空值 None。
请看下面的例子:
knowledge = ['语文', '数学', '英语'] scores = dict.fromkeys(knowledge, 60) print(scores) 输出:{'语文': 60, '英语': 60, '数学': 60}
可以看到,knowledge 列表中的元素全部作为了 scores 字典的键,而各个键对应的值都是 60。
这种创建方式通常用于初始化字典,设置 value 的默认值。
a = dict(str1=value1, str2=value2, str3=value3)
str
表示字符串类型的键,value
表示键对应的值。使用此方式创建字典时,字符串不能带引号。
#方式1 demo = [('two',2), ('one',1), ('three',3)] #方式2 demo = [['two',2], ['one',1], ['three',3]] #方式3 demo = (('two',2), ('one',1), ('three',3)) #方式4 demo = (['two',2], ['one',1], ['three',3]) a = dict(demo)
向 dict()
函数传入列表或元组,而它们中的元素又各自是包含 2 个元素的列表或元组,其中第一个元素作为键,第二个元素作为值。
keys = ['one', 'two', 'three'] #还可以是字符串或元组 values = [1, 2, 3] #还可以是字符串或元组 a = dict( zip(keys, values) )
注意,无论采用以上哪种方式创建字典,字典中各元素的键都只能是字符串
、元组
或数字
,不能是列表。列表是可变的,不能作为键。
如果不为 dict() 函数
传入任何参数,则代表创建一个空的字典,例如:
# 创建空的字典 d = dict() print(d) 输出:{}
列表和元组是通过下标来访问元素的,而字典不同,它通过键来访问对应的值。
因为字典中的元素是无序的,每个元素的位置都不固定,所以字典也不能像列表和元组那样,采用切片的方式一次性访问多个元素。
Python 访问字典元素的具体格式为:
dictname[key]
其中,dictname 表示字典变量的名字,key 表示键名。注意,键必须是存在的,否则会抛出异常。
请看下面的例子:
tup = (['two',26], ['one',88], ['three',100], ['four',-59]) dic = dict(tup) print(dic['one']) #键存在 print(dic['five']) #键不存在 输出: 88 Traceback (most recent call last): File "C:\Users\qinjl\Desktop\demo.py", line 4, in <module> print(dic['five']) #键不存在 KeyError: 'five'
除了上面这种方式外,Python 更推荐使用 dict 类型提供的 get()
方法来获取指定键对应的值。当指定的键不存在时,get()
方法不会抛出异常。
get()
方法的语法格式为:
dictname.get(key[,default])
其中,dictname 表示字典变量的名字;key 表示指定的键;default 用于指定要查询的键不存在时,此方法返回的默认值,如果不手动指定,会返回 None。
a = dict(two=0.65, one=88, three=100, four=-59) print( a.get('one') ) 输出:88
注意,当键不存在时,get()
返回空值 None,如果想明确地提示用户该键不存在,那么可以手动设置 get()
的第二个参数,例如:
a = dict(two=0.65, one=88, three=100, four=-59) print( a.get('five', '该键不存在') ) 输出:该键不存在
和删除列表、元组一样,手动删除字典也可以使用 del
关键字,例如:
a = dict(two=0.65, one=88, three=100, four=-59) print(a) del a print(a) 输出: {'two': 0.65, 'one': 88, 'three': 100, 'four': -59} Traceback (most recent call last): File "C:\Users\qinjl\Desktop\demo.py", line 4, in <module> print(a) NameError: name 'a' is not defined
由于字典属于可变序列,所以我们可以任意操作字典中的键值对(key-value)。Python 中,常见的字典操作有以下几种:
向现有字典中添加新的键值对。
修改现有字典中的键值对。
从现有字典中删除指定的键值对。
判断现有字典中是否存在指定的键值对。
为字典添加新的键值对很简单,直接给不存在的 key 赋值即可,具体语法格式如下:
dictname[key] = value
下面代码演示了在现有字典基础上添加新元素的过程:
a = {'数学':95} print(a) 输出:{'数学': 95} #添加新键值对 a['语文'] = 89 print(a) 输出:{'数学': 95, '语文': 89} #再次添加新键值对 a['英语'] = 90 print(a) 输出:{'数学': 95, '语文': 89, '英语': 90}
Python 字典中键(key)的名字不能被修改,我们只能修改值(value)。
字典中各元素的键必须是唯一的,因此,如果新添加元素的键与已存在元素的键相同,那么键所对应的值就会被新的值替换掉,以此达到修改元素值的目的。请看下面的代码:
a = {'数学': 95, '语文': 89, '英语': 90} print(a) 输出:{'数学': 95, '语文': 89, '英语': 90} a['语文'] = 100 print(a) 输出:{'数学': 95, '语文': 100, '英语': 90}
可以看到,字典中没有再添加一个{'语文':100}
键值对,而是对原有键值对{'语文': 89}
中的 value
做了修改。
如果要删除字典中的键值对,还是可以使用 del
语句。例如:
# 使用del语句删除键值对 a = {'数学': 95, '语文': 89, '英语': 90} del a['语文'] del a['数学'] print(a) 输出:{'英语': 90}
如果要判断字典中是否存在指定键值对,首先应判断字典中是否有对应的键。
判断字典是否包含指定键值对的键,可以使用 in
或 not in
运算符。
需要指出的是,对于 dict 而言,in 或 not in 运算符都是基于 key 来判断的。
a = {'数学': 95, '语文': 89, '英语': 90} # 判断 a 中是否包含名为'数学'的key print('数学' in a) # True # 判断 a 是否包含名为'物理'的key print('物理' in a) # False
通过 in(或 not in)
运算符,我们可以很轻易地判断出现有字典中是否包含某个键,如果存在,由于通过键可以很轻易的获取对应的值,因此很容易就能判断出字典中是否有指定的键值对。
Python 字典的数据类型为 dict,我们可使用 dir(dict)
来查看该类型包含哪些方法,例如:
>>> dir(dict) ['clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
将这三个方法放在一起介绍,是因为它们都用来获取字典中的特定数据:
keys()
方法用于返回字典中的所有键(key
);
values()
方法用于返回字典中所有键对应的值(value
);
items()
用于返回字典中所有的键值对(key-value
)。
请看下面的例子:
scores = {'数学': 95, '语文': 89, '英语': 90} print(scores.keys()) print(scores.values()) print(scores.items()) 输出: dict_keys(['数学', '语文', '英语']) dict_values([95, 89, 90]) dict_items([('数学', 95), ('语文', 89), ('英语', 90)])
可以发现,keys()、values() 、items()
返回值的类型分别为 dict_keys、dict_values 、dict_items
。
在 Python 3.x 中如果想使用这三个方法返回的数据,一般有下面两种方案:
1、使用 list() 函数,将它们返回的数据转换成列表,例如:
a = {'数学': 95, '语文': 89, '英语': 90} print(list(a.keys())) print(list(a.values())) print(list(a.items())) 输出: ['数学', '语文', '英语'] [95, 89, 90] [('数学', 95), ('语文', 89), ('英语', 90)]
2、使用 for in 循环遍历它们的返回值,例如:
a = {'数学': 95, '语文': 89, '英语': 90} for k in a.keys(): print(k, end=' ') print("\n---------------") for v in a.values(): print(v, end=' ') print("\n---------------") for k, v in a.items(): print("key:", k, " value:", v) 输出: 数学 语文 英语 --------------- 95 89 90 --------------- key: 数学 value: 95 key: 语文 value: 89 key: 英语 value: 90
copy()
方法返回一个字典的拷贝,也即返回一个具有相同键值对的新字典,例如:
a = {'one': 1, 'two': 2, 'three': [1,2,3]} b = a.copy() print(b) 输出:{'one': 1, 'two': 2, 'three': [1, 2, 3]}
注意,copy()
方法所遵循的拷贝原理,既有深拷贝,也有浅拷贝。
拿拷贝字典 a
为例,copy()
方法只会对最表层的键值对进行深拷贝,也就是说,它会再申请一块内存用来存放 {'one': 1, 'two': 2, 'three': []}
;
而对于某些列表类型的值来说,此方法对其做的是浅拷贝,也就是说,b 中的 [1,2,3] 的值不是自己独有,而是和 a 共有。
请看下面的例子:
a = {'one': 1, 'two': 2, 'three': [1,2,3]} b = a.copy() #向 a 中添加新键值对,由于b已经提前将 a 所有键值对都深拷贝过来,因此 a 添加新键值对,不会影响 b。 a['four']=100 print(a) print(b) 输出: {'one': 1, 'two': 2, 'three': [1, 2, 3], 'four': 100} {'one': 1, 'two': 2, 'three': [1, 2, 3]} #由于 b 和 a 共享[1,2,3](浅拷贝),因此移除 a 中列表中的元素,也会影响 b。 a['three'].remove(1) print(a) print(b) 输出: {'one': 1, 'two': 2, 'three': [2, 3], 'four': 100} {'one': 1, 'two': 2, 'three': [2, 3]}
从运行结果不难看出,对 a
增加新键值对,b
不变;而修改 a
某键值对中列表内的元素,b
也会相应改变。
update()
方法可以使用一个字典所包含的键值对来更新己有的字典。
在执行 update()
方法时,如果被更新的字典中己包含对应的键值对,那么原 value 会被覆盖;如果被更新的字典中不包含对应的键值对,则该键值对被添加进去(key
存在则更新value
,key
不存在则新增该key-value
)。
请看下面的代码:
a = {'one': 1, 'two': 2, 'three': 3} a.update({'one':4.5, 'four': 9.3}) print(a) 输出:{'one': 4.5, 'two': 2, 'three': 3, 'four': 9.3}
从运行结果可以看出,由于被更新的字典中已包含 key 为“one”的键值对,因此更新时该键值对的 value 将被改写;
而被更新的字典中不包含 key 为“four”的键值对,所以更新时会为原字典增加一个新的键值对。
pop()
和 popitem()
都用来删除字典中的键值对,不同的是,pop() 用来删除指定的键值对,而 popitem() 用来随机删除一个键值对,它们的语法格式如下:
dictname.pop(key) dictname.popitem()
其中,dictname 表示字典名称,key 表示键。
下面的代码演示了两个函数的用法:
a = {'数学': 95, '语文': 89, '英语': 90, '化学': 83, '生物': 98, '物理': 89} print(a) 输出:{'数学': 95, '语文': 89, '英语': 90, '化学': 83, '生物': 98, '物理': 89} a.pop('化学') print(a) 输出:{'数学': 95, '语文': 89, '英语': 90, '生物': 98, '物理': 89} a.popitem() print(a) 输出:{'数学': 95, '语文': 89, '英语': 90, '生物': 98}
对 popitem()
的说明其实,说 popitem()
随机删除字典中的一个键值对是不准确的,虽然字典是一种无须的列表,但键值对在底层也是有存储顺序的,popitem()
总是弹出底层中的最后一个 key-value,这和列表的 pop()
方法类似,都实现了数据结构中“出栈
”的操作。
setdefault()
方法用来返回某个 key 对应的 value,其语法格式如下:
dictname.setdefault(key, defaultvalue)
说明,dictname 表示字典名称,key 表示键,defaultvalue 表示默认值(可以不写,不写的话是 None
)。
当指定的 key 不存在时,setdefault()
会先为这个不存在的 key 设置一个默认的 defaultvalue,然后再返回 defaultvalue (key存在时,返回对应的value;key不存在时,返回默认值
)。
也就是说,setdefault()
方法总能返回指定 key 对应的 value:
如果该 key 存在,那么直接返回该 key 对应的 value(不会更新value);
如果该 key 不存在,那么先为该 key 设置默认的 defaultvalue,然后再返回该 key 对应的 defaultvalue。
请看下面的代码:
a = {'数学': 95, '语文': 89, '英语': 90} print(a) 输出:{'数学': 95, '语文': 89, '英语': 90} #key存在,指定默认值 value = a.setdefault('数学', 100) print(value) print(a) 输出: 95 {'数学': 95, '语文': 89, '英语': 90} #key不存在,指定默认值 value = a.setdefault('物理', 94) print(a) print(value) 输出: 94 {'数学': 95, '语文': 89, '英语': 90, '物理': 94} #key不存在,不指定默认值 a.setdefault('化学') print(a) 输出: {'数学': 95, '语文': 89, '英语': 90, '物理': 94, '化学': None}