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
View Code

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等等

posted @ 2013-08-04 07:07  朗道二级相变  阅读(563)  评论(0编辑  收藏  举报