艰难的扛到第四章,带着无数的问号,版本差异真是大啊。
第四章 字典:当索引不好用时
在之前的章节里,我们学到值是通过编号对其引用的,就像手机号码本只存了电话号码没名字一样,比较麻烦,本章中有了改进,会学到一种通过名字引用值的数据结构,称为映射(mapping)。字典是python中唯一内建的映射类型。字典中的值都存储在一个特定的键(Key)里。
4.1 字典的使用
字典可以轻松查到某个特定的词语(键),从而找到它的定义(值)。
举个栗子,先建立一个存储名字的小型数据库,再建立一个存储他们分机号的数据库,要查找Cecil的分机号,原来的用法是index.
names=['Alice','Beth','Cecil','Dee-Dee','Earl']
numbers=['2341','9102','3158','0142','5551']
numbers[names.index('Cecil')] #返回值'3158',但是比较麻烦,如果有字典就方便了。
4.2 创建和使用字典
字典可以通过下面的方式来创建:
phonebook={'Alice':'2341','Beth':'9102','Cecil':'3258'}
phonebook['Cecil'] #返回'3258',这样引用就很方便了。
空字典就是{}。字典中的键是唯一的,值并不唯一。
4.2.1 dict函数
dict函数是通过其它映射(比如其它字典)或者(键,值)这样的序列对建立字典。
items=[('name','Gumby'),('age',42)]
d=dict(items)
d #返回值{'age': 42, 'name': 'Gumby'},字典建立成功。
d['name'] #返回值'Gumby'
#尝试着用含3个元素的序列来建,报错
items=[('name','Gumby','Ice'),('age',42,36)]
d=dict(items)
#也可以用下面的方式,通过关键字参数
d=dict(name='Gumby',age=42)
d #返回值{'age': 42, 'name': 'Gumby'},效果一样。
4.2.2 基本字典操作
len(d) | 返回d中项(键-值对)的数量 |
d[k] | 返回关联到键k上的值 |
d[k]=v | 将值v关联到键k上 |
del d[k] | 删除键为k的项 |
k in d | 检查d是否有含有键为k的项 |
键类型 | 字典的键不一定是整型数据,也可能是其它不变类型 |
自动添加 | 即使那个键起初在字典中并不存在,也可以为它分配一个值,这样字典会建立新项。 |
成员资格 | 表达式k in d查找的是键,而不是值,v in l则用来查找值,而不是索引 |
x=[]
x[42]='Foobar' #报错
#字典建立不存在的值
x={}
x[42]='Foobar'
x #返回值{42: 'Foobar'}
#简单数据库
#使用人名作为键的字典,每个人用另一个字典表示,其键‘phone'和'addr'分别表示他们的电话号码和地址
people={
'Alice':{
'phone':'2341',
'addr':'Foo drive 23'
},
'Beth':{
'phone':'9102',
'addr':'Bar street 42'
},
'Cecil':{
'phone':'3158',
'addr':'Baz avenue 90'
}
}
#针对电话号码和地址使用的描述性标签,会在打印输出的时候用到
labels = {
'phone':'Phone Number',
'addr':'address'
}
name=input('Names:')
request = input('Phone Number(p) or Address(a)?') #书中漏了这行代码
#查找电话号码还是地址?使用正确的键
#使用正确的键:
if request=='p':key='phone'
if request=='a':key='addr'
#如果名字是字典中的有效键才打印信息
if name in people:print("%s's %s is %s."%\
(name,labels[key],people[name][key]))
4.2.3 字典的格式化字符串
每个转换说明符中的%字符后,可心加上圆括号括起来的键,后面再跟上其它说明元素,例子中用的是s。
phonebook={'Beth':'9102','Alice':'2341','Cecil':'3258'}
"Cecil's phone number is %(Cecil)s."% phonebook #返回值"Cecil's phone number is 3258."这里的s不能省略,会报错。
#简单的html模板生成代码
template = '''
<html>
<head>
<title>%(title)s</title> #s表示用string转换任意python对象
</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)
4.2.4 字典方法
clear | 清除字典中所有的项,原地操作,无返回值 |
copy | 返回同一个具有相同键值对的新字典 |
fromkeys | 使用给定的键建立新的字典 |
get | 提供更宽松的访问字典项的方法 |
in | 检查字典中是否含有给出的键,原来的has_key已取消 |
items | items将所有字典项以列表方式返回,返回时无特殊顺序。iteritems没有了 |
keys | keys方法将字典中的键以列表的形式返回,iterkeys没有了 |
pop | 获得对应于给定键的的值,然后将这个键值对从字典中移除。 |
popitem | 类似于list.pop,后者会弹出列表的最后一个元素。popitem弹出随机的项,字典是无序的。 |
setdefault | 类似于get方法,就是能够获得与给定键相关联的值,此外,还能在字典中不含有给定键的情况下设定相应的键值 |
update | 利用一个字典项更新另外一个字典 |
values | values以列表的形式返回字典中的值,itervalues没有了 |
#clear示例
d={}
d['name']='Gumby'
d['age']=42
d #返回值{'age': 42, 'name': 'Gumby'}
returned_value=d.clear()
d #返回值{},d中的项已经被清空
print(returned_value) #返回值None。
#两种情况
x={}
y=x
x['key']='value'
y #返回值{'key': 'value'},y已被赋值
x={} #x被重新赋值
y #返回{'key': 'value'},x的改变对y不造成影响
x={}
y=x
x['key']='value'
y #返回值{'key': 'value'}
x.clear()
y #返回值{},字典项被清空,想清除原始字典中的元素必须用clear.
#copy示例
x={'username':'admin','machines':['foo','bar','baz']}
y=x.copy()
y['username']='mlh'
y['machines'].remove('bar')
y #返回值{'machines': ['foo', 'baz'], 'username': 'mlh'}
x #返回值{'machines': ['foo', 'baz'], 'username': 'admin'},副本中替换值的时候,原始字典不受影响,修改了的值会改变。
#deepcopy
from copy import deepcopy
d={}
d['names']=['Alfred','Bertrand']
c=d.copy()
dc=deepcopy(d)
d['names'].append('Clive')
c #返回值{'names': ['Alfred', 'Bertrand', 'Clive']}
dc #返回值{'names': ['Alfred', 'Bertrand']}
#from keys示例
{}.fromkeys(['name','age']) #返回值{'age': None, 'name': None},默认值为None。
dict.fromkeys(['name','age']) #返回值{'age': None, 'name': None}
dict.fromkeys(['name','age'],'(unknown)') #返回值{'age': '(unknown)', 'name': '(unknown)'}
#get示例
d={}
print(d['name']) #查找字典中不存在的项会报错
print(d.get('name')) #返回None。
d.get('name','N/A') #返回值'N/A',自定义默认值
d['name']='Eric'
d.get('name') #返回值'Eric',键存在的时候,get用法跟普通字典查询一样。
#使用get()的简单数据库
#复制4.1的代码
people={
'Alice':{
'phone':'2341',
'addr':'Foo drive 23'
},
'Beth':{
'phone':'9102',
'addr':'Bar street 42'
},
'Cecil':{
'phone':'3158',
'addr':'Baz avenue 90'
}
}
#针对电话号码和地址使用的描述性标签,会在打印输出的时候用到
labels = {
'phone':'Phone Number',
'addr':'address'
}
name=input('Names:')
#查找电话号码还是地址?使用正确的键
request = input('Phone Number(p) or Address(a)?')
#使用正确的键:
key=request
if request=='p':key='phone'
if request=='a':key='addr'
#如果名字是字典中的有效键才打印信息
if name in people:print("%s's %s is %s."%\
(name,labels[key],people[name][key]))
#使用get()提供默认数
person=people.get(name,{})
label=labels.get(key,key)
result=person.get(key,'not available')
print("%s's %s is %s."%(name,label,result))
#in示例
d={}
('name') in d #返回值False
#items示例
d={'title':'Python Web Site','url':'http://www.python.org','spam':0}
d.items() #返回值dict_items([('spam', 0), ('url', 'http://www.python.org'), ('title', 'Python Web Site')])
#keys示例
d={}
d.keys() #返回值dict_keys([])
#pop示例
d={'x':1,'y':2}
d.pop('x') #返回值1
d #返回值{'y': 2}。
#popitem示例
d={'url':'http://www.python.org','spam':0,'title':'Python Web Site'}
d.popitem() #返回值('title', 'Python Web Site'),跟书上不一样哦,因为是随机弹出的
d #返回值{'url': 'http://www.python.org', 'spam': 0}
#setdefault示例
d={}
d.setdefault('name','N/A') #返回值'N/A'
d #返回值{'name': 'N/A'}
d['name']='Gumby'
d.setdefault('name','N/A') #返回值'Gumby'
d #返回值{'name': 'Gumby'},当键不存在时setdefaul返回默认值并更新字典,如果键存在,就返回与其对应的值,不改变字典
d={}
print(d.setdefault('name')) #返回值None
d #返回值{'name': None}
#update示例
d={
'title':'Python Web Site',
'url':'http://www.python.org',
'changed':'Mar 14 22:09:15 MET 2008'
}
x={'title':'Python Language Website'}
d.update(x)
d #返回值{'changed': 'Mar 14 22:09:15 MET 2008', 'url': 'http://www.python.org', 'title': 'Python Language Website'}。
#values示例
d={}
d[1]=1
d[2]=2
d[3]=3
d[4]=1
d.values() #返回值dict_values([1, 2, 3, 1])