Python程序设计3——字典
1 字典
字典是Python唯一内建的映射类型。字典是键值对的集合。
1.1 字典的使用
某些情况下字典更加好用,比如一个电话列表。注意:电话号码只能用字符串数字表示,否则会出问题。因为电话号码一旦以0开头,就有可能被当做8进制解析,为了避免这个麻烦,就用字符串表示就可以了。用引号包住数字即可。
1.2 创建和使用字典
字典可以通过下面的方式创建:
变量名 = {键名:值名,键名:值名....}
注意:用引号包起来,键值对合在一起被称作项。键和值中间用冒号隔开,项之间用逗号隔开,所有的项用大括号包起来,叫做字典。空字典就是一对大括号{}.
例如
phonebook = {'Alice':'1234','Beth':'9102'}
1.2.1 dict函数
可以用dict函数,通过其他映射比如字典或者(键,值)来建立字典
>>> items = [('name','Gumble'),('age',42)] >>> d = dict(items) >>> d {'age': 42, 'name': 'Gumble'} >>> d['name'] 'Gumble'
dict函数也可以通过关键字参数来创建字典
>>> d = dict(name = 'Gumble',age = 42) >>> d {'age': 42, 'name': 'Gumble'}
1.3 基本字典操作
字典很多基本行为与序列类似,以字典d为例
1.len(d)返回d中项(键值对)的数量
2.d[k]返回关联到键k上的值
3.d[k] = v,修改d[k]索引的值
4.del d[k]删除键为k的项
5.k in d检查d中是否有含有键为k的项
尽管字典和列表有很多特性相同,但也有一些区别,如下:
1.键值类型:字典的键值不一定为整型数据,也可能是其他不可变类型,如浮点型、字符串或元组,甚至是一个字典
2.自动添加:即使那个键起初在字典中并不存在,也可以为它分配一个值,这样字典就会建立一个新的项,而列表在不适用append方法或者其他类似操作时,不能将值关联到列表范围之外的索引上。
3.成员资格:表达式k in d (d为字典)查找的键,而不是值,表达式v in l(l为列表)则用来查找值,而不是索引
在字典中检查键的成员资格比在列表中检查值的成员资格更高效,数据结构规模越大,两者效率差距越明显。
下面是一个存储号码的字典示例
''' Created on 2013-8-3 @author: Landau ''' #coding=utf-8 #简单数据库 #使用人名作为键的字典,phone表示电话,addr表示地址 people = { 'Alice':{ 'phone':'1345', 'addr':'abcd' }, 'Bob':{ 'phone':'232', 'addr':'adfasf' } } #针对电话号码用的描述性标签 labels = { 'phone':'phone number', 'addr':'address' } name = raw_input('Name: ') request = raw_input('Phone number(p) or address(a)?') #使用正确的键 if(request == 'p'):key = 'phone' if(request == 'a'):key = 'address' #如果名字是字典中有效的键,才会答应 if(name in people):print "%s's %s is %s" % (name,labels[key],people[name][key]) Name: Alice Phone number(p) or address(a)?p Alice's phone number is 1345
1.4 字典的格式化字符串
我们已经见过如何使用字符串格式化功能来格式化元组中的所有值,如果使用(只以字符串作为键的)字典而不是元组来做这个工作,会使字符串格式化可读性更好。在每个转换说明符中的%字符后面,可以加上键,后面跟上其他说明元素
>>> "Alice's phone number is %(Alice)s" % phonebook "Alice's phone number is 1234"
当以这种方式使用字典的时候,只要所有给出的键都能在字典中找到,就可以获得任意数量的转换说明符。这类字符串格式化在模板系统中非常有用。
template = '''<html> <head><title>%(title)s</title></head> <body> <p>%(text)s</p> </body> </html> ''' data = {'title':'lOVE','text':'I love you'} print template % data 输出: <html> <head><title>lOVE</title></head> <body> <p>I love you</p> </body> </html>
1.5 字典方法
字典有很多有用的方法。
1.clear
clear方法清除字典所有的项,这个方法是清除堆内存中的数据,是一种原地操作(针对指针指向的数据的)(类似于list.sort),返回值是None
>>> d = {} >>> d {} >>> d['name'] = 'Gumby' >>> d['age'] = 42 >>> d {'age': 42, 'name': 'Gumby'} >>> returned_value = d.clear() >>> d {} >>> print returned_value None >>>
2.copy
copy方法返回一个具有相同键值对的新字典(这个方法实现的是浅复制),并不是一个副本。
>>> x = {'username':'admin','machines':['for','bar','baz']} >>> y = x.copy() >>> y['username'] = 'mlh' >>> y['machines'].remove('bar') >>> y {'username': 'mlh', 'machines': ['for', 'baz']} >>> x {'username': 'admin', 'machines': ['for', 'baz']}
可以看到,副本在替换值的时候,原始字典不受影响,但如果修改(原地修改,而不是替换)了某个值,原始字典也会改变。
避免这个问题方法是使用深复制,复制其包含所有值。使用copy模块的deepcopy函数
>>> from copy import deepcopy >>> d = {} >>> d['names'] = ['Jack','Alice'] >>> c = d.copy(); >>> dc = deepcopy(d) >>> d['names'].append('Clive') >>> c {'names': ['Jack', 'Alice', 'Clive']} >>> dc {'names': ['Jack', 'Alice']}
从上面两个例子可以看出,浅复制只复制了某些值,而其他值处于共享状态,这样共享值被改变后,所有的都会改变,而深复制则复制了全部,相互之间的改变不受影响。
3.fromkeys
fromkeys方法使用给定的键建立新的字典,每个键默认对应的值为None
>>> {}.fromkeys(['name','[age]']) {'[age]': None, 'name': None}
也可以直接在所有字典类型dict上调用方法
>>> dict.fromkeys(['name','[age]']) {'[age]': None, 'name': None}
如果不想使用None作为默认值,也可以自己提供默认值
{'[age]': '(unknown)', 'name': '(unknown)'}
4.get
get方法是个更宽松的访问字典项的方法,一般来说,如果试图访问字典中不存在的项时会出错。
>>> d = {} >>> print d['name'] Traceback (most recent call last): File "<pyshell#36>", line 1, in <module> print d['name'] KeyError: 'name'
而用get方法就不会
>>> print d.get('name') None
可以看到,当使用get访问一个不存在的键时,没有任何异常,而得到了None值,还可以自定义默认值替换None
>>> print d.get('name','N/A') N/A
如果值存在,就可以像正常访问一样。
>>> d['name'] = 'Jack' >>> d.get('name') 'Jack'
5.has_key
has_key方法可以检查字典中是否含有给出的键。表达式d.has_key(k)相当于表达式k in d。使用哪个方式很大程度上取决于个人的洗好。Python3.0中不包括这个函数
>>> d = {} >>> d.has_key('name') False >>> d['name'] = 'Jack' >>> d.has_key('name') True
6.items和iteritems
items方法将所有的字典项以列表方式返回,这些列表项中的每一项都来自于(键,值)。但是项在返回时并没有特殊的顺序
>>> d = {'title':'Python Web Site','url':'http://www.python.org','spam':0} >>> d.items() [('url', 'http://www.python.org'), ('spam', 0), ('title', 'Python Web Site')] >>> d.iteritems() <dictionary-itemiterator object at 0x01BA1D20> >>> it = d.iteritems() >>> list(it) [('url', 'http://www.python.org'), ('spam', 0), ('title', 'Python Web Site')
注意iteritems方法的作用大致相同,但是iteritems返回的是一个迭代器对象,而不是列表。通常情况下iteritems更高效
7.keys和iterkeys
keys方法将字典的键以列表形式返回,而iterkeys则返回针对键的迭代器
8.pop
pop方法用来获得对应于给定键的值,然后将这个键-值对从字典中移除
>>> d.pop('spam') 0
9.popitem
popitem方法类似于list.pop,后者会弹出列表的最后一个元素,但不同的是popitem弹出随机项,因为字典并没有最后的元素或者其他相关顺序的概念,若想一个接一个地移除这个方法就很有效。
10.setdefault
setdefault方法在某种程度上类似于get方法,就是能够获得与给定键相关联的值,除此之外还可以在不给定键或值的情况下设定相应的键值
>>> d = {} >>> d.setdefault('name','N/A') 'N/A' >>> d {'name': 'N/A'} >>> d['name'] = 'Gumby' >>> d.setdefault('name','N/A') 'Gumby' >>> d {'name': 'Gumby'}
可以看到,当键不存在的时候,setdefault返回默认值,并且相应地更新字典,如果键存在,那么就返回与其对应的值,但不改变字典。默认值可选。
11.update
update方法可以利用一个字典项更新另外一个字典,谁调用该方法,谁被更新
>>> d = {'Jack':'1234','Alice':'8778'} >>> x = {'Jack':'4321'} >>> d.update(x) >>> d {'Jack': '4321', 'Alice': '8778'}
可以看到d的Jack键对应的值被更新了
12.values和itervalues
values方法以列表形式返回字典的值(itervalues返回值列表的迭代器),与返回键的列表不同的是,键是唯一的,而返回值的列表中可以包含重复的元素
>>> d {'Jack': '4321', 'Alice': '8778'} >>> d.values() ['4321', '8778'] >>> list(d.itervalues()) ['4321', '8778']
1.6 小结
映射:映射可以使用任何不可变对象标识元素,最常用的类型是字符串和元组,Python唯一内建的映射类型是字典
利用字典格式化字符串:可以通过在格式化说明符中包括名称(键)来对字典应用字符串格式化操作,当在字符格式化中使用元组时,还需对元组中每一个元素都设定格式化说明符。在使用字典时,所用的说明符可以比字典中用到的项少。
字典的方法:字典有很多方法,比如get、setdefault、keys等等