第4章 字典:当索引不好用时

字典是Python中唯一内建的映射类型.字典中的值并没有特殊的顺序,但是都存储在一个特定的键(Key)下.键可以是数字/字符串甚至是元组.

1. 字典的使用

  • 表示一个游戏棋盘的状态,每个键都是由坐标值组成的元组;
  • 存储文件修改时间,用文件名作为键.
  • 数字电话/地址簿.

2. 创建和使用字典

  • 字典可以通过下面的方式创建 :
    phonebook = {'Kevin':'520','Leona':'1314'}

字典由多个键及其对应的值构成的键-值对组成,在上面的例子中,名字是键,数字则是值.每个键和它的值之间用冒号(:)隔开,项之间用逗号(,)隔开,而整个字典都是由一对大括号括起来.空字典(不包括任何项)由两个大括号组成,像这样 : {}.

2.1 dict函数

dict函数,通过其它映射(比如其他字典)或者(键,值)对的序列建立字典.

1
2
3
4
5
>>> items = [('name','kevin'),('age',21)]
>>> d = dict(items)
>>> d['name']
'kevin'
>>>

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

1
2
3
4
>>> d = dict(name="Kevin",age=42)
>>> d
{'age': 42, 'name': 'Kevin'}
>>>

2.2 基本字典操作

字典的基本行为在很多方面与序列(sequence)类型 :

  • len(d)返回d中项(键-值对)的数量;
  • d[k]返回关联到键k上的值;
  • d[k] = v 将值v关联到见k上;
  • del d[k] 删除键为k的项
  • k in d 检查d中是否有含有键为k的项.
  • 键类型 : 字典的键不一定为整数类型,键可以是任意的不可变类型,比如浮点型(实型),字符串或者元组.
  • 自动添加 : 即使键起初在字典中并不存在,也可以为它赋值,这样字典就会建立新的项.
  • 成员资格 : 表达式 k in d(d为字典)查找的键,而不是值.表达式v in l(l为列表)则用来查找值,而不是索引.

键可以是任意不可变类型 :

1
2
3
4
5
>>> x = {}
>>> x[12] = 'kevin'
>>> x
{12: 'kevin'}
>>>

2.3 字典的格式化字符串

1
2
3
>>> "Cecil's phone number is %(Cecil)s."%phonebook
"Cecil's phone number is 3258."
>>>

2.4 字典方法

  • clear
    clear方法清除字典中所有的项.这个是原地操作,所以无返回值.
1
2
3
4
5
6
7
8
>>> d = {}
>>> d['name'] = 'kevin'
>>> d
{'name': 'kevin'}
>>> d.clear()
>>> d
{}
>>>
  • copy
    copy方法返回一个具有相同键-值对的新字典.(这个方法实现的浅复制,因为值本身就是相同的,而不是副本.)
1
2
3
4
5
>>> x = {'username':'admin','pasword':123456}
>>> y = x.copy()
>>> y
{'username': 'admin', 'pasword': 123456}
>>>

但是,如果修改了某个值(原地修改,而不是替换),原始的值也会改变,因为同样的值存储在原字典中.模块的deepcopy函数来完成操作.

1
2
3
4
5
6
7
8
9
>>> from copy import deepcopy
>>> d = {}
>>> d['names'] = ['Kevin','Leona']
>>> c = d.copy()
>>> dc = deepcopy(d)
>>> d['names'].append('Clive')
>>> c
{'names': ['Kevin', 'Leona', 'Clive']}
>>>
  • fromkeys
    fromkeys方法使用给定的键建立新的字典,每个键都对应一个默认的的值None.
1
2
3
>>> {}.fromkeys(['name','age'])
{'age': None, 'name': None}
>>>
  • get
    get方法是个更宽松的字典项的方法,当使用get访问一个不存在的键时,没有任何异常,而得到了None值.还可以自定义”默认值”,替换None.
1
2
>>> d.get('name','N/A')
'N/A'
  • has_key
    has_key方法可以检查字典中是否有特定的键.表达式d.has_key(k)相当于表达式k in d.
1
2
3
4
5
6
>>> d = {'name':'kevin'}
>>> d.has_key('name')
True
>>> d.has_key("password")
False
>>>
  • items和iteritems
    items方法将所有字典的项以列表方式返回,列表中的每一项都表示为(键,值)对的形式.但是项在返回时并没有遵循特定的次序.

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

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

1
2
3
4
5
6
>>> d = {'x':1,'y':2}
>>> d.pop('x')
1
>>> d
{'y': 2}
>>>
  • popitem
    popitem方法类似于list.pop,后者会弹出列表的最后一个元素.

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

1
2
3
4
5
>>> d.setdefault('name','N/A')
'N/A'
>>> d['name'] = 'kevin'
>>> d.setdefault('name','N/A')
'kevin'

可以看到,当键不存在的时,setdefault返回默认值并且相应地更新字典.如果键存在,那么就返回与其对应的值,但不改变字典.默认值是可选的,这点和get一样.

  • update
    update方法可以利用一个字典项更新另外一个字典 :
1
2
3
4
5
6
>>> d = {'title':'python Web Site','url':'http://www.python.org'}
>>> x = {'title':'python language website'}
>>> d.update(x)
>>> d
{'url': 'http://www.python.org', 'title': 'python language website'}
>>>
  • values和itervalues
    values方法以列表的形式返回字典中的值(itervalues返回值的迭代器).与返回键的列表不同的是,返回值的列表中可以包含重复的元素.
1
2
3
4
5
6
>>> d = {}
>>> d[1] = 1
>>> d[2] = 2
>>> d.values()
[1, 2]
>>>

3. 小结

  • 映射 : 映射可以使用任意不可变对象标识元素,最常用的类型是字符串和元组.
  • 利用字典格式化字符串 : 可以通过在格式化说明中包括名称(键)来对字典应用字符串格式化操作.当在字符格式化中使用元组时,还需要对元组中每一个元素都设定”格式化说明符”.在使用字典时,所有的说明符可以比在字典中用到的项少.
  • 字典的方法 : 字典很多方法,调用的方式和调用列表以及字符串方法的方式相同.