字典概述

字典属于映射类型,将可哈希对象映射到任意对象,可哈希对象为字典的键,映射的对象为键对应的条目(值)。因此:

  • 键必须是可哈希且唯一的;
  • 值可以是任意对象(此处 值 仅指键对应的条目)。

所以字典的键必须是可哈希对象,例如字符串,元组(不能包含不可哈希对象);哈希值相等的对象作为字典的键会被当作一个键。

{'1':1, (1,2):2, 1:3, True:4}
{'1': 1, (1, 2): 2, 1: 4}

字典是目前唯一的标准映射类型。其类型为 dict。空字典用一对花括号表示。

type({})
dict

字典可以通过花括号包含逗号分隔的 键值对 来创建,也可以用内置函数 dict() 来创建。

{'a':1, 'b':2}
{'a': 1, 'b': 2}
dict(a=1,b=2)
{'a': 1, 'b': 2}
dict(zip(['a','b'],(1,2)))
{'a': 1, 'b': 2}

字典是可变对象,可以通过键,来获取对应的项,或更新、添加项。获取项时,键不存在则引发 KeyError。

# 获取
d = {'a':1}
d['a']
1
# 更新
d['a'] = [1,2]
d
{'a': [1, 2]}
# 键不存在则添加项
d['b'] = {1,2}
d
{'a': [1, 2], 'b': {1, 2}}
d['c']
---------------------------------------------------------------------------

KeyError                                  Traceback (most recent call last)

<ipython-input-9-05ba6e0488c7> in <module>
----> 1 d['c']


KeyError: 'c'

字典的元素(键值对)是按哈希值来存储的,没有序列类型的双向索引操作,但字典会保留元素插入时的顺序,更新不会改变插入顺序。而且使用 popitem 方法删除元素是按后进先出原则删除。

d = {}
d[3] = 3
d[1] = 1
d[2] = 2
d
{3: 3, 1: 1, 2: 2}
d[1] = 10
d
{3: 3, 1: 10, 2: 2}
d.popitem(),d.popitem(),d.popitem()
((2, 2), (1, 10), (3, 3))

dict.keys 键视图

字典方法 dict.keys(),Python 官方文档描述如下:

help(dict.keys)
Help on method_descriptor:

keys(...)
    D.keys() -> a set-like object providing a view on D's keys

返回一个由字典的键组成的动态视图。字典的视图支持成员检测,可以被迭代。

d = {'a':1, 'b':2}
d.keys()
dict_keys(['a', 'b'])
'a' in d.keys()
True
list(d.keys())
['a', 'b']
d = {'a':1, 'b':2}
d_view = d.keys()
print(d_view)
d['c'] = 3 # 添加元素,视图也动态变化
print(d_view)
dict_keys(['a', 'b'])
dict_keys(['a', 'b', 'c'])

dict.values 值视图

字典方法 dict.values(),Python 官方文档描述如下:

help(dict.values)
Help on method_descriptor:

values(...)
    D.values() -> an object providing a view on D's values

返回由字典的值组成的动态视图。字典的视图支持成员检测,可以被迭代。

d = {'a':1, 'b':2}
d_view = d.values()
print(d_view)
d['c'] = 3 # 添加元素,视图也动态变化
print(d_view)
dict_values([1, 2])
dict_values([1, 2, 3])
1 in d_view
True
[i for i in d_view]
[1, 2, 3]

dict.items 键值对视图

字典方法 dict.items(),Python 官方文档描述如下:

help(dict.items)
Help on method_descriptor:

items(...)
    D.items() -> a set-like object providing a view on D's items

返回字典的 (键,值) 元组组成的动态视图。字典的视图支持成员检测,可以被迭代。

d = {'a':1, 'b':2}
d_view = d.items()
print(d_view)
d['c'] = 3 # 添加元素,视图也动态变化
print(d_view)
dict_items([('a', 1), ('b', 2)])
dict_items([('a', 1), ('b', 2), ('c', 3)])
('a', 1) in d_view
True
[k*j for k, j in d_view]
['a', 'bb', 'ccc']

dict.get 获取某个键的值

字典方法 dict.get(),Python 官方文档描述如下:

help(dict.get)
Help on method_descriptor:

get(self, key, default=None, /)
    Return the value for key if key is in the dictionary, else default.

获取字典的项目,如果 key 存在于字典中则返回 key 的值,否则返回 default 指定的值,默认为 None。

d = {'a':1, 'b':2}
d.get('a')
1
print(d.get('c'))
None
d.get('c', 3)
3

dict.copy 浅拷贝

字典方法 dict.copy(),Python 官方文档描述如下:

help(dict.copy)
Help on method_descriptor:

copy(...)
    D.copy() -> a shallow copy of D

返回字典的一个浅拷贝。字典是可变对象,浅拷贝将创建一个新字典,但如果字典中某个 键值对 的值是可变对象,则是同一个对象的多次引用。

d = {'a':[1,2], 'b':3}
print(id(d), d)
d1 = d.copy()
print(id(d1), d1)
2276967660712 {'a': [1, 2], 'b': 3}
2276967660784 {'a': [1, 2], 'b': 3}
# 同一个对象的多次引用
id(d['a']), id(d1['a'])
(2276966678024, 2276966678024)
# 改变一个都会改变
d['a'].extend('34')
print(d)
print(d1)
{'a': [1, 2, '3', '4'], 'b': 3}
{'a': [1, 2, '3', '4'], 'b': 3}

dict.pop 删除元素并返回值

字典方法 dict.pop(),Python 官方文档描述如下:

help(dict.pop)
Help on method_descriptor:

pop(...)
    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

如果字典的键 k 存在,则移除 k 对应的 键值对,并返回 值;

如果 k 不存在,但指定了可选参数 d,则返回 d;

如果 k 不存在且未指定 d,则引发 KeyError。

d = {'a':1, 'b':2}
d.pop('a')
1
d = {'a':1, 'b':2}
d.pop('c', 3)
3
d = {'a':1, 'b':2}
d.pop('c')
---------------------------------------------------------------------------

KeyError                                  Traceback (most recent call last)

<ipython-input-4-1e5ab2c0b86c> in <module>
      1 d = {'a':1, 'b':2}
----> 2 d.pop('c')


KeyError: 'c'

dict.popitem 删除元素并返回键值对

字典方法 dict.popitem(),Python 官方文档描述如下:

help(dict.popitem)
Help on method_descriptor:

popitem(self, /)
    Remove and return a (key, value) pair as a 2-tuple.
    
    Pairs are returned in LIFO (last-in, first-out) order.
    Raises KeyError if the dict is empty.

按 后进先出 的原则,删除字典的元素,并以 (key, value) 元组返回。如果字典为空,则引发 KeyError。

d = {2:2,1:1}
d.popitem()
(1, 1)
d = {}
d[1] = 1
d[3] = 3
d[2] = 2
d[3] = 30 # 更新并不改变元素插入顺序
d.popitem(),d.popitem(),d.popitem()
((2, 2), (3, 30), (1, 1))
d = {}
d.popitem()
---------------------------------------------------------------------------

KeyError                                  Traceback (most recent call last)

<ipython-input-13-3d5a99fd0340> in <module>
      1 d = {}
----> 2 d.popitem()


KeyError: 'popitem(): dictionary is empty'

dict.fromkeys 创建字典

字典的方法 fromkeys,Python 官方文档描述如下:

help(dict.fromkeys)
Help on built-in function fromkeys:

fromkeys(iterable, value=None, /) method of builtins.type instance
    Create a new dictionary with keys from iterable and values set to value.

使用可迭代对象 iterable 中的元素作为字典的键,value 为值(默认是 None)创建字典。

dict.fromkeys('123')
{'1': None, '2': None, '3': None}
dict.fromkeys([1,2,3], 0)
{1: 0, 2: 0, 3: 0}

可迭代对象中不能包含不可哈希对象:

dict.fromkeys([[1],2,3], 0)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-6-470a0d0c77b4> in <module>
----> 1 dict.fromkeys([[1],2,3], 0)


TypeError: unhashable type: 'list'

dict.clear 清空字典元素

字典方法 dict.clear(),Python 官方文档描述如下:

help(dict.clear)
Help on method_descriptor:

clear(...)
    D.clear() -> None.  Remove all items from D.

清空字典元素。

d = {'a':1, 'b':2}
d.clear()
d
{}

该方法是一个过程,返回值为 None。

d = {'a':1, 'b':2}
print(d.clear())
None

dict.setdefault 获取或插入元素

字典方法 dict.setdefault(),Python 官方文档描述如下:

help(dict.setdefault)
Help on method_descriptor:

setdefault(self, key, default=None, /)
    Insert key with a value of default if key is not in the dictionary.
    
    Return the value for key if key is in the dictionary, else default.

如果字典存在键 key,则返回它的值;如果 key 不存在,则插入 key,以 default(默认 None)作为它的值,并返回。

d = {'a':1, 'b':2}
d.setdefault('a')
1
d.setdefault('c', 3)
3
d
{'a': 1, 'b': 2, 'c': 3}
d.setdefault('c', 4) # 如果存在,并不会再次设置
3
d
{'a': 1, 'b': 2, 'c': 3}

dict.update 更新字典

字典方法 dict.update(),Python 官方文档描述如下:

help(dict.update)
Help on method_descriptor:

update(...)
    D.update([E, ]**F) -> None.  Update D from dict/iterable E and F.
    If E is present and has a .keys() method, then does:  for k in E: D[k] = E[k]
    If E is present and lacks a .keys() method, then does:  for k, v in E: D[k] = v
    In either case, this is followed by: for k in F:  D[k] = F[k]

更新字典,键相同,则覆盖原有的值,不同,则增加 键值对 元素。有下列几种情况:

  • 以字典更新字典:
d = {'a':1, 'b':2}
d.update({'a':10, 'c':3})
d
{'a': 10, 'b': 2, 'c': 3}
  • 以可迭代对象更新字典:
d = {'a':1, 'b':2}
d.update([('a',10),['c',3]])
d
{'a': 10, 'b': 2, 'c': 3}
  • 以关键字参数更新字典:
d = {'a':1, 'b':2}
d.update(a=10, c=3)
d
{'a': 10, 'b': 2, 'c': 3}

字典遍历

字典是可迭代对象,可以遍历字典的元素。由于字典元素是 键值对,遍历比较特殊。

如果未指定遍历对象,默认遍历字典的键。很多函数将字典作为可迭代对象处理时,也是如此。

d = {'a':1, 'c':3, 'b':2}
for k in d:
    print(k)
a
c
b
list(d)
['a', 'c', 'b']
sorted(d)
['a', 'b', 'c']
max(d)
'c'

可以利用字典的视图指定遍历字典的键(默认就是遍历键,可以省略),值 或是 键值对。

d = {'a':1, 'c':3, 'b':2}
for k in d.keys(): # 可以不用视图
    print(k)
a
c
b
d = {'a':1, 'c':3, 'b':2}
for k in d.values(): 
    print(k)
1
3
2
d = {'a':1, 'c':3, 'b':2}
for k,v in d.items(): 
    print(k,v)
a 1
c 3
b 2
# 按值排序后再遍历
d = {'a':1, 'c':3, 'b':2}
for k,v in sorted(d.items(),key=lambda x:x[1]): 
    print(k,v)
a 1
b 2
c 3

字典操作符

字典不可以使用比较大小的操作符 <, <=, >=>,会引发 TypeError。

{1:1} < {2:2}
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-1-8ea82599b938> in <module>
----> 1 {1:1} < {2:2}


TypeError: '<' not supported between instances of 'dict' and 'dict'

字典比较相等时,当且仅当 键值对 都相等时才相等。

{1:1.0, 2:2} == {2:2, True:1}
True
{1:'1', 2:2} == {2:2, 1:1}
False

字典可以使用 ** 操作符进行拆包,拆包后置于新字典中,可以用来更新字典;或拆包后作为关键字参数传递给函数。

{'a':1, 'b':2, **{'a':10}}
{'a': 10, 'b': 2}
d = {'a':1, 'b':2}
'a={a},b={b}'.format(**d)
'a=1,b=2'

Python 3.9 新版,实现了两个操作符 ||=

{'a':1} | {'b':2}
{'a': 1, 'b': 2}

合并 d 和 other 中的键和值来创建一个新的字典,两者必须都是字典。当 d 和 other 有相同键时,other 的值优先。

{'a':1} | {'a':5, 'b':2}
{'a': 5, 'b': 2}

用 other 的键和值更新字典 d ,other 可以是映射(mapping)或可迭代对象(iterable)的键值对。当 d 和 other 有相同键时,other 的值优先。