字典是 Python 中内建的一种具有弹性储存能力的数据结构,可存储任意类型对象,与序列使用整数索引不同,它使用键(key)进行索引。
通常任何不变类型的对象均可作为索引,比如数字,字符串和元组,列表可以被修改,不可作为键。由于键作为索引使用,所以它必须是唯一的。
字典的每个键都有对应的值 (value),键值对用冒号 “:” 分割,每个键值对之间用逗号 “,” 分割,整个字典包括在花括号 {} 中。
直接创建字典
dict_empty = {} # 可以创建空字典 key = 'abc' dict0 = {1: None,'abc': 1, (1, 2): "tuple key", key: "replaced"} print (dict0) print (dict0[1]) print (dict0[key]) print (dict0[(1,2)]) >>> {1: None, 'abc': 'replaced', (1, 2): 'tuple key'} None replaced tuple key
可以看到如果,出现重复的键,比如这里的 ‘abc’ ,则最后的一个键值会替换前面的,键对应的值可以是任意数据类型, 不同的键可以对应相同的值
访问字典
字典以键为索引访问对应的值,如果键不存在,抛出 KeyError :
print(dict0[2]) >>> File "C:/Users/Red/.spyder/dictest.py", line 16, in <module> print (dict0[2]) KeyError: 2
D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
字典方法 D.get() 方法可以在键不存在时返回指定的值,如果不指定则默认返回 None 。
0 1 2 3 4 5 | print(dict0[2]) print(dict0.get(2, "hello")) >>> None hello |
间接创建字典
包含键值对的( key-value)序列,使用 dict() 进行类型转换。
0 1 2 3 4 5 | list0 = [('key0', 1), ('key2', None), (3, ['1', '2'])] # 可以是元组类型 dict0 = dict(list0) print(dict0) >>> {'key0': 1, 'key2': None, 3: ['1', '2']} |
通过参数对序列,也可以创建字典,但是关键字必须是字符串:
0 1 2 3 4 | dict0 = dict(key0=1, key1="abc") print(dict0) >>> {'key0': 1, 'key1': 'abc'} |
7.1.3.1. 字典推导
类似列表推导,字典推导(dict comprehension),可以简化代码。
0 1 2 3 4 5 6 7 | dict0 = {x: x**2 for x in [1, 2, 3]} dict1 = {x: "/home/" + x + '.jpg' for x in ("pic0", "pic1")} print(dict0) print(dict1) >>> {1: 1, 2: 4, 3: 9} {'pic0': '/home/pic0.jpg', 'pic1': '/home/pic1.jpg'} |
7.1.3.2. zip 合并
zip()函数名副其实,它的作用很像拉链,将两个列表合并成一个 zip 对象,dict() 可以把它转化为字典。
0 1 2 3 4 | dict0 = dict(zip(['one', 'two', 'three'], [1, 2, 3])) print(dict0) >>> {'one': 1, 'two': 2, 'three': 3} |
7.1.3.3. 由列表生成定值字典
D.fromkeys(iterable, value=None, /) method of builtins.type instance Returns a new dict with keys from iterable and values equal to value.
D.fromkeys() 方法支持从迭代对象取键,并可指定值的字典。通常使用列表或者元组作为参数。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 | seq = ['key0', 'key1'] # 也可为元组,字符串等可迭代对象 dict0 = dict.fromkeys(seq) # 字典所有值均为 None dict1 = dict.fromkeys(seq, 10) # 字典所有值均为 10 dict2 = dict.fromkeys(seq, [1, 2]) # 字典所有值均为 [1, 2] dict3 = dict.fromkeys('123', 10) # 一次从字符串中取一个字符作为键 for i in range(4): print("dict%d:\t%s" % (i, eval("dict" + str(i)))) >>> dict0: {'key0': None, 'key1': None} dict1: {'key0': 10, 'key1': 10} dict2: {'key0': [1, 2], 'key1': [1, 2]} dict3: {'1': 10, '2': 10, '3': 10} |
如果序列中出现重复成员,在生成的字典中它作为键只会出现一次。
7.2. 字典操作
7.2.1. 键值添加和更新
0 1 2 3 4 5 6 7 8 9 | dict0 = {} dict0['key0'] = "val0" # 添加键值对 print(dict0) dict0['key0'] = 123 # 更新键的值 print(dict0) >>> {'key0': 'val0'} {'key0': 123} |
键值不存在时更新
D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
与直接对键赋值不同,D.setdefault() 方法可以在键存在时不做操作,而在键不存在时更新键值对。
0 1 2 3 4 5 6 7 8 9 10 11 12 | dict0 = {'key0': 'val0'} dict0['key1'] = 'val1' # 直接赋值 print(dict0) dict0.setdefault('key1', "newval") # key1 存在,不做操作 print(dict0) dict0.setdefault('key2', "newval") # key2 不存在,插入 print(dict0) >>> {'key0': 'val0', 'key1': 'val1'} {'key0': 'val0', 'key1': 'val1'} {'key0': 'val0', 'key1': 'val1', 'key2': 'newval'} |
7.2.3. 更新键值对
D.update() 方法把一个迭代对象(通常为字典)中的键值对更新到当前字典中,如果键存在则覆盖。
0 1 2 3 4 5 6 7 8 9 10 | dict0 = {'key0': 'val0'} dict1 = {'key0': 0, "key1" : [1, 2]} dict0.update(dict1) dict0.update([("name", "value")]) # 其他含键值对的可迭代对象 # 即便释放 dict1 不影响 dict0 值,是完全复制 del(dict1) print(dict0) >>> {'key0': 0, 'key1': [1, 2], 'name': 'value'} |
7.2.4. 删除键值和清空字典
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | dict0 = {"key0" : "val0", "key1" : "val1"} del dict0['key0'] # 删除键值 print(dict0) dict0.clear() # 清空字典 print(dict0) del(dict0) # 删除dict0变量,释放资源 print(dict0) # NameError 找不到 dict0 变量 >>> {'key1': 'val1'} {} ...... NameError: name 'dict0' is not defined |
del() 函数删除dict0变量,不可再被使用。D.clear() 方法只清空字典,字典可以被访问。
7.2.5. 按键访问并删除
D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
If key is not found, d is returned if given, otherwise KeyError is raised
D.pop() 方法删除字典给定键 key 所对应的成员,并返回它对应的值,如果键不存在返回参数指定的默认值。
0 1 2 3 4 5 6 7 8 | dict0 = {'key0': 0, 'key1': [1, 2]} print(dict0.pop('key0', "default")) print(dict0) print(dict0.pop('key5', "default")) >>> 0 {'key1': [1, 2]} default |
7.2.6. 随机遍历访问
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | dict0 = {"key0" : "val0", "key1" : "val1"} for i in dict0: # 默认迭代字典键序列 print(i, end=' ') print("\n") for i in dict0.values(): # 迭代字典值序列 print(i, end=' ') print("\n") for i in dict0.items(): # 迭代字典键值对 print(i) >>> key0 key1 val0 val1 ('key0', 'val0') ('key1', 'val1') |
使用字典内建的 D.values() 方法和 D.items()方法可以方便循环处理每一个成员。
7.2.7. 遍历删除
D.popitem() 内建方法随机返回并删除字典中的一对键和值,为元组类型。字典不可为空,否则会报错。
0 1 2 3 4 5 6 7 8 9 10 | dict0 = {'key0': 0, 'key1': [1, 2], 'name': 'value'} for i in range(len(dict0)): item = dict0.popitem() print(item) print(dict0) # 空字典 >>> ('name', 'value') ('key1', [1, 2]) ('key0', 0) {} |
示例中可以看出字典是无序的,并没有按照成员赋值的顺序,而是按照键的 ASCII 码排序。
7.2.8. 字典复制
类似列表,字典也支持深浅拷贝,字典自带的 D.copy() 方法是浅拷贝,借助 copy 模块实现深拷贝。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | dict0 = {'key0': 'val0', 'list' : [1, 2, 3]} dict1 = dict0 # 引用对象 dict2 = dict1.copy() # 浅拷贝:只复制父对象一级,子对象不复制,还是引用 import copy dict3 = copy.deepcopy(dict0) #深拷贝,完全复制 dict1['key0'] = 'newval' del dict1['key0'] # 删除会影响引用 dict0 dict0['list'][0] = 'a' # 改变子对象值,影响浅拷贝 dict2,不影响深拷贝 dict3 for i in range(4): print("dict%d:\t%s" % (i, eval("dict" + str(i)))) >>> dict0: {'list': ['a', 2, 3]} dict1: {'list': ['a', 2, 3]} dict2: {'key0': 'val0', 'list': ['a', 2, 3]} dict3: {'key0': 'val0', 'list': [1, 2, 3]} |
7.2.9. 字典和字符串转换
通过 str() 类型转化方法可以把字典转换位字符串:
0 1 2 3 4 5 | dict0 = {'key0': 'val0', 'list' : [1, 2, 3]} str0 = str(dict0) print(str0) >>> {'key0': 'val0', 'list': [1, 2, 3]} |
字符串转字典通常有两种方式,eval() 方法和 json 模块提供的 json.loads() 方法。
0 1 2 3 4 5 6 7 8 9 | dict0 = eval(str0) # eval 方法 print(dict0) import json # 使用 json 模块 dict1 = json.loads("\"" + str0 + "\"") # 或 repr(str0) print(dict1) >>> {'key0': 'val0', 'list': [1, 2, 3]} {'key0': 'val0', 'list': [1, 2, 3]} |
注意,采用 json 模块时字符串前后必须添加引号,简单的方式为 repr(str0)
。
7.2.10. 字典相等比较
Python2.x 版本使用 cmp() 方法比较字典,Python3 取消了该方法,直接使用比较运算符。
0 1 2 3 4 5 6 7 8 | dict0 = {'key0': 0, 'key1': [1, 2]} dict1 = {'key0': 0, 'key2': [1, 2]} print(dict0 == dict1) print(dict0 != dict1) >>> False True |
字典不可以比较大小,只可以比较是否相等,相等即指字典所有的键值对完全相同。
7.2.11. 字典排序
由于字典本身是无需的,所以需要转换为有序的对象,例如列表。字典对象的 items() 方法可以转换为可迭代对象,迭代对象的元素为元组,形式为 (‘key’, value),然后使用 sorted 函数通过参数 key 指定排序所用的关键字。
0 1 2 3 4 5 6 7 8 9 10 11 12 | # 按 key 排序 In [58]: scores = {'John': 15, 'Bill': 18, 'Kent': 12} ...: new_scores = sorted(scores.items(), key=lambda x:x[1], reverse=False) ...: print(new_scores) ...: [('Kent', 12), ('John', 15), ('Bill', 18)] # 按 value 排序 In [59]: scores = {'John': 15, 'Bill': 18, 'Kent': 12} ...: new_scores = sorted(scores.items(), key=lambda x:x[0], reverse=False) ...: print(new_scores) ...: [('Bill', 18), ('John', 15), ('Kent', 12)] |
7.3. 统计和存在判定
7.3.1. 统计字典元素个数
0 1 2 3 4 | dict0 = {'key0': 'val0', 'key1' : "val1"} print(len(dict0)) >>> 2 |
7.3.2. 键存在判定
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | dict0 = {'key0': 'val0', 'key1' : "val1"} #print(dict0.has_key('a')) # False #print(dict0.has_key('key0')) # True # Python3.x 不再支持 has_key() 方法,被 __contains__(key) 替代 print(dict0.__contains__('a')) print(dict0.__contains__('key0')) # 或者使用 key in 判断,not in 执行反操作 print('a' in dict0) print('a' not in dict0) >>> False True False True |
通常使用 in
或者 not in
成员运算符。