映射类型是一种关联式的容器类型,它存储了对象与对象之间的映射关系。简而言之就是通过名称来访问其各个值的数据结构,这种数据结构称为映射(mapping)。
字典是Python中唯一一个内置的映射类型,其中的值不按顺序排列,而是存储在键下。键可以是数、字符串或者元组。
Python中的字典由键及其相应的值组成,这种键-值对称为项(item)。每个键与值之间都用冒号:分割,项之间用逗号隔开,而整个字典放在**花括号{}**内。
d = {
key1 : value1, key2 : value2 } #字典的形式表示
phonebook = {
'Alice':'1234', 'Bob':'9102','Cat':'3258'}
注意
:在字典(以及其他映射类型)中,键必须是独一无二
的,而值无需如此。
可以用函数dict从其他映射(如其他字典)或键-值对序列创建字典。
>>> item = [('name','Alice'),('age',21)]
>>> d = dict(item)
>>> d
{
'age': 21, 'name': 'Alice'}
>>> d['name']
'Alice'
还可以用关键字实参来调用这函数
>>> d = dict(name='Alice',age=21,id='12345')
>>> d
{
'age': 21, 'id': '12345', 'name': 'Alice'}
如上图,也可以使用一个映射实参来调用它,这将创建一个包含指定映射中所有项的字典。特别的,若该映射也是字典,则我们可以使用字典方法copy。
字典的基本操作在很多方面类似于序列。
方法 | 描述 |
---|---|
len(d) | 返回字典d包含的项(键-值对)数 |
d[k] | 返回与键k相关联的值 |
d[k] = v | 值v关联到键k |
del [k] | 删除键k的项 |
k in d | 检查字典d是否包含键k的项 |
不同之处:
键的类型: 字典中的键可以是整数也可以是非整数。字典中的键可以是任何不可变
的值,如浮点数、字符串或元组。
自动添加: 即使字典中原来没有键,也可以给它赋值,这将在字典中创建一个新项。然而,如果不适用append或其它方法,就不能给列表中原有的元素赋值。
成员资格表达式k in d(d是一个字典)查找的是键而不是值,而表达式v in l(l 是一个列表)查找的是值而不是索引。
删除所有的字典项,因此什么都不返回也可以说返回None
>>> x = {
}
>>> y = x
>>> x['key'] = 'value'
>>> y
{
'key': 'value'}
>>> x = {
}
>>> y
{
'key': 'value'}
如果用clear来进行清除,则y也是空的。
>>> x = {
}
>>> y = x
>>> y
{
}
>>> x['key'] = 'value'
>>> y
{
'key': 'value'}
>>> x.clear()
>>> y
{
}
返回一个新字典,其包含的键-值对与原来的字典相同(这种为浅复制,因为值本身是原件,而非副本)
>>> x = {
'username':'admin','machine':['foo','bar','baz']}
>>> y = x.copy()
>>> y['username'] = 'mlh'
>>> y['machine'].remove('bar')
>>> y
{
'machine': ['foo', 'baz'], 'username': 'mlh'}
>>> x
{
'machine': ['foo', 'baz'], 'username': 'admin'}
正如你所看见的,发生了一件很诡异的事情:
为了避免上述的问题,可执行深复制,用到copy模块中的函数deepcopy
>>> from copy import deepcopy
>>> d = {
'names':['Alice','Bob'], 'loca':'china'}
>>> a = d
>>> c = d.copy()
>>> dc = deepcopy(d)
>>> print(d == c )
True
>>> print(d == dc )
True
>>> print(dc is c)
False
看上去相同,但不是同一个对象。
此时改变d的值:
>>> d['local'] = 'England' #操作1
>>> d['names'].append('Cat') #操作2
再查看结果:
>>> d
{
'local': 'England', 'names': ['Alice', 'Bob', 'Cat'], 'loca': 'china'}
>>> a
{
'local': 'England', 'names': ['Alice', 'Bob', 'Cat'], 'loca': 'china'}
>>> c
{
'names': ['Alice', 'Bob', 'Cat'], 'loca': 'china'}
>>> dc
{
'names': ['Alice', 'Bob'], 'loca': 'china'}
发现,操作1和2均改变了d和其引用a,
但是c只受操作2的影响,dc不受影响。
因为c是a的浅拷贝,值拷贝了父对象,而d的子对象列表[‘Alice’, ‘Bob’]改变时c也会收到影响;但是dc是深拷贝。完全不受影响。
此时,可能有人还不明白,我的理解是:
独立的新个体
单独存在。所以改变原有被复制对象不会对已经复制出来的新对象产生影响新名字(新标签)
,他们都引用同一块内存,所以当一个标签被改变时,数据块就会发生改变。类似于下面代码:
>>> a = [1,2,3]
>>> b = a # b是a的引用
>>> a = [4,5,6] # 当a重新引用到另一内存块时,b不会有影响,还是引用
>>> print(a) # 原来内存块
[4, 5, 6]
>>> print(b)
[1, 2, 3]
>>> a = [1,2,3]
>>> b = a
>>> a[0],a[1],a[2] = 4,5,6 # 但是改变a中元素的值,b也会变
>>> print(a)
[4, 5, 6]
>>> print(b)
[4, 5, 6]
所以,可以把浅复制中对子对象只是创建一个引用。
创建一个新字典,其中包含指定的键,且每个键对应夫人值都是None
>>> dict.fromkeys(['name','age'])
{
'name': None, 'age': None}
>>> dict.fromkeys(['name','age'],'(unknown)') #提供默认值
{
'name': '(unknown)', 'age': '(unknown)'}
>>> dict.fromkeys(['name','age'],'myvalue')
{
'name': 'myvalue', 'age': 'myvalue'}
如果试图访问字典中没有的元素,将引发错误。
>>> d = {
}
>>> print(d['name'])
Traceback (most recent call last):
File "" , line 1, in <module>
KeyError: 'name'
但是,用get来访问不存在的键时,不会引发异常,而是返回None。而且可以指定值而不是None
>>> d = {
}
>>> d.get('name')
>>> print(d.get('name'))
None
>>> print(d.get('name','error'))
error
返回一个包含所有字典项的列表,其中每个元素都为**(key,value)**的形式,字典项目在列表中排列顺序不确定。
>>> phonebook = {
'Alice':'1234', 'Bob':'9102','Cat':'3258'}
>>> phonebook.items()
dict_items([('Alice', '1234'), ('Cat', '3258'), ('Bob', '9102')])
>>> book = phonebook.items() #列表操作
>>> len(book)
3
>>> ('Alice','1234') in book
True
返回值属于一种名为字典视图的特殊类型。视图的优点是不复制,始终是底层字典的动态反映,即使你修改了底层字典。
>>> phonebook['Alice'] = '2345'
>>> ('Alice','1234') in book
False
>>> phonebook['Alice'] = '1234'
>>> ('Alice','1234') in book
True
返回一个字典视图,包含指定字典中的键。
>>> phonebook = {
'Alice':'1234', 'Bob':'9102','Cat':'3258'}
>>> phonebook.keys()
dict_keys(['Alice', 'Cat', 'Bob'])
获取与指定键相关的值,并将该键-值对从字典中删除。
>>> phonebook = {
'Alice':'1234', 'Bob':'9102','Cat':'3258'}
>>> phonebook.pop('Alice')
'1234'
>>> phonebook
{
'Cat': '3258', 'Bob': '9102'}
不用指定键值,随机弹出一个字典项,可用于快速逐个删除并处理所有字典项。
用法类似于get,获得与指定键相关联的值。但是,会在不包含指定键值的时候,在字典中添加键值对。
>>> d = {
}
>>> d.setdefault('name','myvalue')
'myvalue'
>>> d
{
'name': 'myvalue'}
>>> d.setdefault('name','error')
'myvalue'
使用一个字典中的项来更新另一个字典。
>>> book = {
'Alice':'1234', 'Bob':'9102','Cat':'3258'}
>>> person = {
'Alice':'2345'}
>>> book.update(person)
>>> book
{
'Alice': '2345', 'Cat': '3258', 'Bob': '9102'}
>>> new = {
'Dog':'1998'}
>>> book.update(new)
>>> book
{
'Dog': '1998', 'Alice': '2345', 'Cat': '3258', 'Bob': '9102'}
更新包含相同键值的项,添加没有的。
返回一个由字典中值组成的字典视图,与keys恰好互补,但是方法values可能返回的视图包含重复值。
>>> d = {
1:1,2:2,3:3,4:1}
>>> d.keys()
dict_keys([1, 2, 3, 4])
>>> d.values()
dict_values([1, 2, 3, 1])
1.Beginning Python From Novice to Professional Third Edition. Magnus Lie Hetland 著
2.Python标准英文文档