艱難的扛到第四章,帶着無數的問號,版本差異真是大啊。
第四章 字典:當索引不好用時
在之前的章節裏,我們學到值是通過編號對其引用的,就像手機號碼本只存了電話號碼沒名字一樣,比較麻煩,本章中有了改進,會學到一種通過名字引用值的數據結構,稱爲映射(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])