字典

字典:当索引不好用时。

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

1.字典的使用

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

  a.表示一个游戏盘的状态,每个键都是由坐标组成的元组;

  b.存储文件修改时间,用文件作为键;

  c.数字电话/地址薄

2.创建和使用字典

  字典创建方式如下:

1 phonebook = {'Alice':'3241','Beth':'9102'}

  字典有多个键及其对应的值构成的键-值对组成(我们把键-值对称为项),每个键和它的值之间使用冒号(:)隔开,项于项之间用逗号隔开。空字典由{}组成

  注意:字典的键是唯一的(其他类型的映射也是如此),而值并不是唯一的。

  1.dict函数

  可以用dict函数(dict函数根本不是真正的函数,他是个类型),通过其他映射(比如其他字典)或者(键值)对的列表建立字典

1 >>> items = [('name','Gumby'),('age',42)]
2 >>> d = dict(items)
3 >>> d
4 {'name': 'Gumby', 'age': 42}
5 >>> d['name']
6 'Gumby'

  dict函数也可以通过关键字参数来创建字典,如下所示:

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

  2.基本字典操作

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

  • len(d)返回中项(键值对)的数量
  • d[k]返回关联到键k的值
  • d[k]=v将值v关联到键k上;
  • del d[k]删除键k的项;
  • k in d检查d中是否又含有键为K的项

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

  • 键类型:字典的键不一定为整型数据,键可以是任意的不可变类型,比如浮点型(实型)、字符串或者元组。
  • 自动添加:即使键起初在字典中并不存在,也可以为它赋值,这样字典就会建立新的项。而(在不适用append方法或者其他类似操作的情况下)不能将值关联到列表范围之外的索引上。
  • 成员资格:表达式k in d(d为字典)查找的键,而不是值。表达式v in l(l为列表)则用来查找值,而不是索引。这样看起来好像有些不太一致,但是当习惯以后就会感觉非常自然了。

  提示:在字典检查的成员资格比在列表中检查的成员资格更高效,数据结构的规模越大,两者的效率差距越明显。

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

  第二点:举例说明,见一下例子

1 >>> x=[]
2 >>> x[42]='Foobar'
3 Traceback (most recent call last):
4   File "<stdin>", line 1, in <module>
5 IndexError: list assignment index out of range
6 >>> x = {}
7 >>> x[42]='Foobar'
8 >>> x
9 {42: 'Foobar'}

  首先,程序试图将字符串‘Foobar’关联到一个空列表的42号位置上——这显然是不可能的,应为这个位置根本不存在。为了将其变得可能,必须用[None]*43或者其他方法初始化x,而不能仅使用[]。但是,下一个例子工作得很好。将'Foobar'关联到空字典的键42上(能成功加入,这也说明了字典的无序性),结果成功加入。

  电话本例子的代码如下:

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8-*-
 3 people = {
 4     'Alice': {
 5         'phone': '2341',
 6         'addr': 'Foo drive 23'
 7     },
 8     'Beth': {
 9         'phone': '9120',
10         'addr': 'Bar street 43'
11     },    
12     'Cecil': {
13         'phone': '3158',
14         'addr': 'Baz avenue 90'
15     }
16 }
17 # 针对电话号码和地址使用的描述性标签,输出时使用到
18 labels = {
19     'phone': 'phone number',
20     'addr': 'address'
21 }
22 # 输出所有用户的名字
23 print(people.keys())
24 
25 # 提示用户数据要查找的姓名
26 name = input('Name: ')
27 
28 print(people[name].values())
29 # 查找电话号码还是地址
30 request = input('Phone Number(p) or Address(a)?')
31 # 根据使用的键,做对应输出:
32 if request == 'p': key = 'phone'
33 if request == 'a': key = 'addr'
34 
35 # 最后输出校验,如果名字是字典中有效键才打印信息
36 if name in people:print( "%s's %s is %s."%\
37     (name,labels[key],people[name][key]))
38 
39 运行结果如下:
40 dict_keys(['Cecil', 'Beth', 'Alice'])
41 Name: Cecil
42 dict_values(['Baz avenue 90', '3158'])
43 Phone Number(p) or Address(a)?p
44 Cecil's phone number is 3158.

  3.字典的格式化字符串

  使用字典(只以字符串作为键的)而不是元组,会使字符串格式化更简单更酷一些。在每个转换说明符中的%字符后面,可以加上键(用圆括号括起来),后面再跟上其他说明元素。

  示例如下:

1 >>> phonebook={'Beth':'9102','Alice':'2314','Cecil':'3258'}
2 >>> "Cecil's phone number is %(Cecil)s."%phonebook
3 "Cecil's phone number is 3258."

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

__author__ = 'Administrator'
template = '''
<html>
<head><title>%(title)s</title></head>
<body>
    <h1>%(title)s</h1>
    <p>%(text)s</p>
</body>
</html>
'''
data = {'title':'My Home Page','text':'Welcome to my home page!'}
print(template%data)

运行结果如下:
<html>
<head><title>My Home Page</title></head>
<body>
    <h1>My Home Page</h1>
    <p>Welcome to my home page!</p>
</body>
</html>

  注意:string.Template类对于这类应用也是非常用用的。

  4.字典方法

  4.1 clear

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

 1 >>> d = {}
 2 >>> d['name']='Gumby'
 3 >>> d['age']=23
 4 >>> d
 5 {'name': 'Gumby', 'age': 23}
 6 >>> returned_value = d.clear()
 7 >>> d
 8 {}
 9 >>> returned_value
10 >>> print(returned_value)
11 None

  4.2 copy

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

 1 >>> x = {'username':'admin','machines':['foo','bar','baz']}
 2 >>> y = x.copy()
 3 >>> y['username'] = 'mlh'
 4 >>> y
 5 {'machines': ['foo', 'bar', 'baz'], 'username': 'mlh'}
 6 >>> y['machines'].remove('bar')
 7 >>> y
 8 {'machines': ['foo', 'baz'], 'username': 'mlh'}
 9 >>> x
10 {'machines': ['foo', 'baz'], 'username': 'admin'}

  可以看到,当在副本中替换值是,原始字典不受影响,但是,如果修改了某个值(原地修改,而不是替换),原始字典也会改变。因为同样的值也存在原字典中(就像上面例子中的machine列表一样)。

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

 1 >>> from copy import deepcopy
 2 >>> d = {}
 3 >>> d['names'] = ['Alfred','Bertrand']
 4 >>> c = d.copy()
 5 >>> dc = c.deepcopy(d)
 6 Traceback (most recent call last):
 7   File "<stdin>", line 1, in <module>
 8 AttributeError: 'dict' object has no attribute 'deepcopy'
 9 >>> dc = deepcopy(d)
10 >>> d['names'].append('Clive')
11 >>> c
12 {'names': ['Alfred', 'Bertrand', 'Clive']}
13 >>> dc
14 {'names': ['Alfred', 'Bertrand']}

  4.3 fromkeys

  fromkeys方法使用给定的键值建立新的字典,每个键都对应一个默认的值None.

1 >>> {}.fromkeys(['name','age'])
2 {'name': None, 'age': None}

  4.4 get

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

1 >>> d = {}
2 >>> print(d['name'])
3 Traceback (most recent call last):
4   File "<stdin>", line 1, in <module>
5 KeyError: 'name'
>>> d = {}
>>> print(d['name'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'name'
#而用get就不会
>>> print(d.get('name'))
None

  字典方法示例

 1 #字典方法示例(get)
 2 #使用get()的简单数据库
 3 lables = {
 4     'phone':'phone number',
 5     'addr':'address'
 6 }
 7 
 8 name = input('Name:')
 9 
10 #查找电话号码还是地址?
11 request = input('Phone number(p) or address(a)? ')
12 
13 #使用正确的键
14 key = request # 如果请求既不是'p'也不是'a'
15 if request=='p':key = 'phone'
16 if request=='a':key = 'address'
17 
18 #使用get()提供默认值
19 people = {}
20 person = people.get(name,{})
21 lable = lables.get(key,key)
22 result = person.get(key,'not available')
23 
24 print("%s's %s is %s."%(name,lable,result))
25 
26 =================================
27 运行结果如下:
28 Name:tom
29 Phone number(p) or address(a)? s
30 tom's s is not available.

  4.5 items和iteritems

  items方法将字典所有的项以列表方式返回,列表中的每一项都表示对应的形式。但是项再返回时并没有遵循特定的秩序。

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

 

  4.6 pop

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

  

  4.7 popitem

  popitem方法类似于list.pop,后者会弹出列表的最后一个元素。但不同的是,popitem弹出随机的项,因为字典并没有“最后的元素”或者其他有关顺序的概念。若想一个接一个的移除并处理项,这个方法就非常有用了(因为不用首先获取键的列表)。

1 >>> d = {'url':'http://www.python.org','span':0,'title':'Python Web Site'}
2 >>> d.popitem()
3 ('span', 0)
4 >>> d
5 {'title': 'Python Web Site', 'url': 'http://www.python.org'}

  

  

  

  

 

posted on 2016-01-28 01:25  揉碎的青春  阅读(184)  评论(0编辑  收藏  举报

导航