首页 > 代码库 > python基础教程_学习笔记6:字典

python基础教程_学习笔记6:字典

字典

映射(mapping),一种可通过名字引用值得数据结构。

字典是python中唯一内建的映射类型。

字典中的值没有特殊的顺序,但都存储在一个特定的键(key)里。键可以是数字、字符串甚至是元组。

 

字典的使用

某些情况下,字典比列表更加适用,比如:

表征游戏棋盘的状态,每个键都是由坐标值组成的元组;

存储文件修改数,用文件名作为键;

数字电话/地址簿;

 

假如有一个人名列表如下:

>>>names=[‘Alice‘,‘Beth‘,‘Cecil‘,‘Dee-Dee‘,‘Earl‘]

如果要创建一个可以存储这些人的电话号码的小型数据库,应该怎么做呢?

一种方法是建立一个新的列表,依次存储这些人的电话号码:

>>>teles=[‘2341‘,‘0102‘,‘3158‘,‘3291‘,‘5551‘]

建立了这些列表后,可以通过如下方式查找Cecil的电话号码:

>>> teles[names.index(‘Cecil‘)]

‘3158‘

为什么用字符串而不用整数表示电话号码呢?我们来试试如果用整数表示会怎样?

>>>names=[‘Alice‘,‘Beth‘,‘Cecil‘,‘Dee-Dee‘,‘Earl‘]

>>>teles=[2341,0102,3158,3291,5551]

>>> teles[names.index(‘Cecil‘)]

3158

>>> teles[names.index(‘Beth‘)]

66

Beth的电话号码显然不是我们想要的结果。因为0开头的是八进制数字,返回的结果是十进制数字。

 

创建和使用字典

字典可以通过以下方式创建:

phonebook={‘Alice‘:‘2341‘,‘Beth‘:‘9102‘,‘Cecil‘:‘3258‘}

 

字典由多个键以及其对应的值构成的对组成(也把键值对成为项)。每个键和它的值之间用冒号隔开,项之间用逗号隔开,而整个字典由一对大括号括起来。

空字典(不包括任何项)由两个大括号组成,像这样:{}

注意:字典中的键是唯一的,而值并不唯一。

dict函数

可以用dict函数,通过其他映射(比如其他字典)或者(键、值)这样的序列对建立字典。

>>>items=[(‘name‘,‘Gumby‘),(‘age‘,42)]

>>> d=dict(items)

>>> d

{‘age‘: 42, ‘name‘: ‘Gumby‘}

>>> d[‘name‘]

‘Gumby‘

 

dict函数也可以通过关键字参数来创建字典:

>>> d=dict(name=‘signjing‘,age=28)

>>> d

{‘age‘: 28, ‘name‘: ‘signjing‘}

如果不带任何参数,则dict函数返回一个新的空字典。

>>> d=dict()

>>> d

{}

基本字典操作

字典的基本行为在很多方面与序列类似:

 

len(d)返回d中项(键值对)的数量;

>>>phonebook={‘Alice‘:‘2341‘,‘Beth‘:‘9102‘,‘Cecil‘:‘3258‘}

>>> len(phonebook)

3

d[k]返回关联到键k上的值;

>>> phonebook[‘Cecil‘]

‘3258‘

d[k]=v将值关联到键k上;

>>> phonebook[‘Cecil‘]=‘8888‘

>>> phonebook

{‘Beth‘: ‘9102‘, ‘Alice‘: ‘2341‘, ‘Cecil‘:‘8888‘}

del d[k]删除键为k的值;

>>> del phonebook[‘Alice‘]

>>> phonebook

{‘Beth‘: ‘9102‘, ‘Cecil‘: ‘8888‘}

k in d检查d中是否含有键为k的项;

>>> ‘signjing‘ in phonebook

False

>>> ‘Beth‘ in phonebook

True

 

尽管字典和列表有很多特性相同,但也有下面一些重要的区别:

键类型:字典的键不一定为整数数据,也可能是其他不可变类型。

自动添加即使那个键起初在字典中不存在,也可以为它分配一个值,这样字典就会自动建立该项。而不能将值关联到列表范围之外的索引上。

成员资格:表达式k in d(字典)查找的是键,而不是值。表达式v in l(列表)则用来查找值,而不是索引。(在字典中检查键的成员资格比在列表中检查值的成员资格更高效,数据结构的规模越大,两者的效率差距越明显。

 

第一点:键可以为任何不可变类型——是字典最强大的地方。

第二点,也很重要:那个键起初在字典中不存在,也可以为它分配一个值,这样字典就会自动建立该项。

>>> x=[]

>>> x[4]=5

 

Traceback (most recent call last):

 File "<pyshell#30>", line 1, in <module>

   x[4]=5

IndexError: list assignment index out ofrange

>>> x={}

>>> x[42]=‘fool‘

>>> x

{42: ‘fool‘}

 

字典的格式化字符串

 

在每个转换说明符中的%字符后面,可以加上(用圆括号括起来的)键后面再跟上其他说明元素。

>>>phonebook={‘Alice‘:‘2341‘,‘Beth‘:‘9102‘,‘Cecil‘:‘3258‘}

>>> "Cecil‘s phone number is%(Cecil)s." % phonebook

"Cecil‘s phone number is 3258."

 

除了增加的字符串键之外,转换说明符还是像以前一样工作。当以这种方式使用字典的时候,只要所有给出的键都能在字典中找到,就可以获得任意数量的转换说明符。这类字符串格式化在模板系统中非常有用。

 

字典方法

像其他内建类型一样,字典也有方法。这些方法非常有用,但可能不会像使用列表或者字符串方法那样频繁地使用。

clear

clear方法清除字典中所有的项。这是个原地操作(类似于list.sort),所以无返回值(或者返回None)。

>>> return_value=http://www.mamicode.com/d.clear()

>>> d

{}

>>> print return_value

None

copy

copy方法返回一个具有相同键-值对的新字典(实现的是浅复制),因为值本身就是相同的,而不是副本)。

>>>x={‘Alice‘:‘2341‘,‘Beth‘:‘9102‘,‘Cecil‘:‘3258‘}

>>> y=x.copy()

>>> y

{‘Beth‘: ‘9102‘, ‘Alice‘: ‘2341‘, ‘Cecil‘:‘3258‘}

>>> y[‘Beth‘]=‘1111‘

>>> y

{‘Beth‘: ‘1111‘, ‘Alice‘: ‘2341‘, ‘Cecil‘:‘3258‘}

>>> x

{‘Beth‘: ‘9102‘, ‘Alice‘: ‘2341‘, ‘Cecil‘:‘3258‘}

 

可以看到,当在副本中替换值的时候,原始字典不受影响。但是,如果修改了某个值(原地修改,而不是替换),原始字典也会改变,因为同样的值也存储在原字典中。

>>>x={‘Alice‘:‘2341‘,‘Beth‘:‘9102‘,‘Cecil‘:‘3258‘}

>>> y=x

>>> y

{‘Beth‘: ‘9102‘, ‘Alice‘: ‘2341‘, ‘Cecil‘:‘3258‘}

>>> y[‘Beth‘]=‘1111‘

>>> y

{‘Beth‘: ‘1111‘, ‘Alice‘: ‘2341‘, ‘Cecil‘:‘3258‘}

>>> x

{‘Beth‘: ‘1111‘, ‘Alice‘: ‘2341‘, ‘Cecil‘:‘3258‘}

 

避免这个问题的一种方法是使用深复制,复制其包含所有的值。可以使用copy模块的deepcopy函数来完成操作:

>>> from copy import deepcopy

>>> d={}

>>>d[‘names‘]=[‘Alfred‘,‘Bertrand‘]

>>> c=d.copy()

>>> dc=deepcopy(d)

>>> d

{‘names‘: [‘Alfred‘, ‘Bertrand‘]}

>>> dc

{‘names‘: [‘Alfred‘, ‘Bertrand‘]}

>>> c

{‘names‘: [‘Alfred‘, ‘Bertrand‘]}

>>> d[‘names‘].append(‘Clive‘)

>>> c

{‘names‘: [‘Alfred‘, ‘Bertrand‘, ‘Clive‘]}

>>> dc

{‘names‘: [‘Alfred‘, ‘Bertrand‘]}

>>> d

{‘names‘: [‘Alfred‘, ‘Bertrand‘, ‘Clive‘]}

fromkeys

fromkeys方法使用给定的键建立新的字典。每个键默认对应的值为None。

>>> {}.fromkeys([‘name‘,‘age‘])

{‘age‘: None, ‘name‘: None}

也可以在所有字典的类型dict上调用方法:

>>> dict.fromkeys([‘name‘,‘age‘])

{‘age‘: None, ‘name‘: None}

 

如果不想使用None作为默认值,可以自己提供默认值。

>>>dict.fromkeys([‘name‘,‘age‘,‘weight‘],‘(something)‘)

{‘age‘: ‘(something)‘, ‘name‘:‘(something)‘, ‘weight‘: ‘(something)‘}

get

get方法是一个更宽松的访问字典项的方法。一般来说,项不存在时会出错:

>>> d={}

>>> d[‘name‘]=‘signjing‘

>>> print d[‘name‘]

signjing

>>> print d[‘age‘]

 

Traceback (most recent call last):

 File "<pyshell#81>", line 1, in <module>

   print d[‘age‘]

KeyError: ‘age‘

 

如果使用get方法则不出错(string的find方法也不出错,但返回值是-1):

>>> print d.get(‘age‘)

None

>>> print d.get(‘name‘)

signjing

 

还可以自定义“默认”值,替换None:

>>> print d.get(‘age‘,‘unknown‘)

unknown

has_key

has_key方法可以检查字典中是否含有给出的键。表达式d.has_key(k)相当于表达式k in d。使用哪个方式很大程度上取决于个人喜好,但有的版本并不支持它。

>>> d={}

>>> d.has_key(‘age‘)

False

>>> d[‘age‘]=18

>>> d.has_key(‘age‘)

True

items和iteritems

items方法将所有的字典项以列表方式返回,这些列表项的每一项都来自于(键,值)。但是项在返回时并没有特殊的顺序。

 

>>>phonebook={‘Alice‘:‘2341‘,‘Beth‘:‘9102‘,‘Cecil‘:‘3258‘}

>>> phonebook.items()

[(‘Beth‘, ‘9102‘), (‘Alice‘, ‘2341‘),(‘Cecil‘, ‘3258‘)]

 

iteritems方法的作用大致相同,但会返回一个迭代器对象而不是列表:

>>> it=phonebook.iteritems()

>>> it

<dictionary-itemiterator object at0x01232B10>

>>> list(it)

[(‘Beth‘, ‘9102‘), (‘Alice‘, ‘2341‘),(‘Cecil‘, ‘3258‘)]

很多情况下使用iteritems更高效(尤其是想要迭代结果的情况下)。

keys和iterkeys

keys方法将字典中的键以列表形式返回,而iterkeys则返回针对键的迭代器。

pop

pop方法用来获得对应于给定键的值,然后将这个键-值对从字典中移除。

>>> d={‘x‘:1,‘y‘:2}

>>> d.pop(‘x‘)

1

>>> d

{‘y‘: 2}

popitem

popitem方法类似于list.pop,后者弹出列表的最后一个元素,不同的是popitem弹出随机的项(因为字典并没有“最后的元素”或者其他有关顺序的概念。)

>>>phonebook={‘Alice‘:‘2341‘,‘Beth‘:‘9102‘,‘Cecil‘:‘3258‘}

>>> phonebook

{‘Beth‘: ‘9102‘, ‘Alice‘: ‘2341‘, ‘Cecil‘:‘3258‘}

>>> phonebook.popitem()

(‘Beth‘, ‘9102‘)

>>> phonebook

{‘Alice‘: ‘2341‘, ‘Cecil‘: ‘3258‘}

>>> phonebook.popitem()

(‘Alice‘, ‘2341‘)

>>> phonebook

{‘Cecil‘: ‘3258‘}

>>> phonebook.popitem()

(‘Cecil‘, ‘3258‘)

>>> phonebook

{}

 

尽管popitem和列表的pop方法很类似,但字典中并没有与append等价的方法,因为字典是无序的,类似于append的方法没有任何意义。

setdefault

setdefault方法在某种程度上类似于get方法,也就是能够获得与给定键相关联的值,除此之外,setdefault还能在字典中不含有给定键的情况下设定相应的键值。

>>> d={}

>>> d.setdefault(‘name‘,‘N/A‘)

‘N/A‘

>>> d

{‘name‘: ‘N/A‘}

>>> d[‘name‘]=‘signjing‘

>>> d

{‘name‘: ‘signjing‘}

>>> d.setdefault(‘name‘,‘NULL‘)

‘signjing‘

>>> d

{‘name‘: ‘signjing‘}

>>> d.setdefault(‘age‘,‘NULL‘)

‘NULL‘

>>> d

{‘age‘: ‘NULL‘, ‘name‘: ‘signjing‘}

 

当键不存在时,setdefault返回默认值并相应地更新字典。

如果键存在,则返回与其对应的值,但不改变字典。默认值是可选的,这点同get一样。如果不设定,则默认使用None。

update

update方法可以利用一个字典项更新另外一个字典:

>>>people1={‘name‘:‘A‘,‘age‘:‘20‘,‘weight‘:‘100‘}

>>>people2={‘name‘:‘B‘,‘length‘:‘175‘}

>>> people1

{‘length‘: ‘175‘, ‘age‘: ‘20‘, ‘name‘: ‘B‘,‘weight‘: ‘100‘}

>>> people2

{‘length‘: ‘175‘, ‘name‘: ‘B‘}

 

 

>>> people1={‘name‘:‘A‘,‘age‘:‘20‘,‘weight‘:‘100‘}

>>>people2={‘name‘:‘B‘,‘length‘:‘175‘}

>>> people2.update(people1)

>>> people1

{‘age‘: ‘20‘, ‘name‘: ‘A‘, ‘weight‘: ‘100‘}

>>> people2

{‘age‘: ‘20‘, ‘length‘: ‘175‘, ‘name‘: ‘A‘,‘weight‘: ‘100‘}

values和itervalues

values方法以列表的形式返回字典中的值(itervalues返回值的迭代器)。与返回键的列表不同的是,返回值的列表中可以包含重复的元素(因为字典的值是可以相同的):

>>> d={}

>>> d[1]=1

>>> d[2]=2

>>> d[3]=1

>>> d

{1: 1, 2: 2, 3: 1}

>>> d.values()

[1, 2, 1]