字典(1)

2018-02-24 15:48 更新

字典,這個(gè)東西你現(xiàn)在還用嗎?隨著網(wǎng)絡(luò)的發(fā)展,用的人越來(lái)越少了。不少人習(xí)慣于在網(wǎng)上搜索,不僅有web版,乃至于已經(jīng)有手機(jī)版的各種字典了。我在上小學(xué)的時(shí)候曾經(jīng)用過一本小小的《新華字典》,記得是拾了不少?gòu)U品,然后換錢,最終花費(fèi)了1.01元人民幣買的。

《新華字典》是中國(guó)第一部現(xiàn)代漢語(yǔ)字典。最早的名字叫《伍記小字典》,但未能編纂完成。自1953年,開始重編,其凡例完全采用《伍記小字典》。從1953年開始出版,經(jīng)過反復(fù)修訂,但是以1957年商務(wù)印書館出版的《新華字典》作為第一版。原由新華辭書社編寫,1956年并入中科院語(yǔ)言研究所(現(xiàn)中國(guó)社科院語(yǔ)言研究所)詞典編輯室。新華字典由商務(wù)印書館出版。歷經(jīng)幾代上百名專家學(xué)者10余次大規(guī)模的修訂,重印200多次。成為迄今為止世界出版史上最高發(fā)行量的字典。

這里講到字典,不是為了回憶青蔥歲月。而是提醒看官想想我們?nèi)绾问褂米值洌合炔樗饕ú还苁瞧匆暨€是偏旁查字),然后通過索引找到相應(yīng)內(nèi)容。不用從頭開始一頁(yè)一頁(yè)地找。

這種方法能夠快捷的找到目標(biāo)。

正是基于這種需要,python中有了一種叫做dictionary的數(shù)據(jù)類型,翻譯過來(lái)就是“字典”,用dict表示。

假設(shè)一種需要,要存儲(chǔ)城市和電話區(qū)號(hào),蘇州的區(qū)號(hào)是0512,唐山的是0315,北京的是011,上海的是012。用前面已經(jīng)學(xué)習(xí)過的知識(shí),可以這么來(lái)做:

>>> citys = ["suzhou", "tangshan", "beijing", "shanghai"]
>>> city_codes = ["0512", "0315", "011", "012"]

用一個(gè)列表來(lái)存儲(chǔ)城市名稱,然后用另外一個(gè)列表,一一對(duì)應(yīng)地保存區(qū)號(hào)。假如要輸出蘇州的區(qū)號(hào),可以這么做:

>>> print "{} : {}".format(citys[0], city_codes[0])
suzhou : 0512

請(qǐng)?zhí)貏e注意,我在city_codes中,表示區(qū)號(hào)的元素沒有用整數(shù)型,而是使用了字符串類型,你知道為什么嗎? 如果用整數(shù),就是這樣的。

>>> suzhou_code = 0512
>>> print suzhou_code
330

怎么會(huì)這樣?原來(lái)在python中,如果按照上面那樣做,0512并沒有被認(rèn)為是一個(gè)八進(jìn)制的數(shù),用print打印的時(shí)候,將它轉(zhuǎn)換為了十進(jìn)制輸出。關(guān)于進(jìn)制轉(zhuǎn)換問題,看官可以網(wǎng)上搜索一下有關(guān)資料。此處不詳述。一般是用幾個(gè)內(nèi)建函數(shù)實(shí)現(xiàn):int(),?bin(),?oct(),?hex()

這樣來(lái)看,用兩個(gè)列表分別來(lái)存儲(chǔ)城市和區(qū)號(hào),似乎能夠解決問題。但是,這不是最好的選擇,至少在python里面。因?yàn)閜ython還提供了另外一種方案,那就是字典(dict)。

創(chuàng)建dict

方法1:

創(chuàng)建一個(gè)空的dict,這個(gè)空dict,可以在以后向里面加?xùn)|西用。

>>> mydict = {}
>>> mydict
{}

不要小看“空”,“色即是空,空即是色”,在編程中,“空”是很重要。一般帶“空”字的人都很有名,比如孫悟空,哦。好像他應(yīng)該是猴、或者是神。舉一個(gè)人的名字,帶“空”字,你懂得。

創(chuàng)建有內(nèi)容的dict。

>>> person = {"name":"qiwsir","site":"qiwsir.github.io","language":"python"}
>>> person
{'name': 'qiwsir', 'language': 'python', 'site': 'qiwsir.github.io'}

"name":"qiwsir",有一個(gè)優(yōu)雅的名字:鍵值對(duì)。前面的name叫做鍵(key),后面的qiwsir是前面的鍵所對(duì)應(yīng)的值(value)。在一個(gè)dict中,鍵是唯一的,不能重復(fù)。值則是對(duì)應(yīng)于鍵,值可以重復(fù)。鍵值之間用(:)英文的分號(hào),每一對(duì)鍵值之間用英文的逗號(hào)(,)隔開。

>>> person['name2']="qiwsir"    #這是一種向dict中增加鍵值對(duì)的方法
>>> person
{'name2': 'qiwsir', 'name': 'qiwsir', 'language': 'python', 'site': 'qiwsir.github.io'}

用這樣的方法可以向一個(gè)dict類型的數(shù)據(jù)中增加“鍵值對(duì)”,也可以說(shuō)是增加數(shù)值。那么,增加了值之后,那個(gè)字典還是原來(lái)的嗎?也就是也要同樣探討一下,字典是否能原地修改?(列表可以,所以列表是可變的;字符串和元組都不行,所以它們是不可變的。)

>>> ad = {}
>>> id(ad)
3072770636L
>>> ad["name"] = "qiwsir"
>>> ad
{'name': 'qiwsir'}
>>> id(ad)
3072770636L

實(shí)驗(yàn)表明,字典可以原地修改,即它是可變的。

方法2:

利用元組在建構(gòu)字典,方法如下:

>>> name = (["first","Google"],["second","Yahoo"])      
>>> website = dict(name)
>>> website
{'second': 'Yahoo', 'first': 'Google'}

或者用這樣的方法:

>>> ad = dict(name="qiwsir", age=42)
>>> ad
{'age': 42, 'name': 'qiwsir'}

方法3:

這個(gè)方法,跟上面的不同在于使用fromkeys

>>> website = {}.fromkeys(("third","forth"),"facebook")
>>> website
{'forth': 'facebook', 'third': 'facebook'}

需要提醒的是,這種方法是重新建立一個(gè)dict。

需要提醒注意的是,在字典中的“鍵”,必須是不可變的數(shù)據(jù)類型;“值”可以是任意數(shù)據(jù)類型。

>>> dd = {(1,2):1}
>>> dd
{(1, 2): 1}
>>> dd = {[1,2]:1}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

訪問dict的值

dict數(shù)據(jù)類型是以鍵值對(duì)的形式存儲(chǔ)數(shù)據(jù)的,所以,只要知道鍵,就能得到值。這本質(zhì)上就是一種映射關(guān)系。

映射,就好比“物體”和“影子”的關(guān)系,“形影相吊”,兩者之間是映射關(guān)系。此外,映射也是一個(gè)嚴(yán)格數(shù)學(xué)概念:A是非空集合,A到B的映射是指:A中每個(gè)元素都對(duì)應(yīng)到B中的某個(gè)元素。

既然是映射,就可以通過字典的“鍵”找到相應(yīng)的“值”。

>>> person
{'name2': 'qiwsir', 'name': 'qiwsir', 'language': 'python', 'site': 'qiwsir.github.io'}
>>> person['name']
'qiwsir'
>>> person['language']
'python'

如同前面所講,通過“鍵”能夠增加dict中的“值”,通過“鍵”能夠改變dict中的“值”,通過“鍵”也能夠訪問dict中的“值”。

本節(jié)開頭那個(gè)城市和區(qū)號(hào)的關(guān)系,也可以用字典來(lái)存儲(chǔ)和讀取。

>>> city_code = {"suzhou":"0512", "tangshan":"0315", "beijing":"011", "shanghai":"012"}
>>> print city_code["suzhou"]
0512

既然dict是鍵值對(duì)的映射,就不用考慮所謂“排序”問題了,只要通過鍵就能找到值,至于這個(gè)鍵值對(duì)位置在哪里就不用考慮了。比如,剛才建立的city_code

>>> city_code
{'suzhou': '0512', 'beijing': '011', 'shanghai': '012', 'tangshan': '0315'}

雖然這里顯示的和剛剛賦值的時(shí)候順序有別,但是不影響讀取其中的值。

在list中,得到值是用索引的方法。那么在字典中有索引嗎?當(dāng)然沒有,因?yàn)樗鼪]有順序,哪里來(lái)的索引呢?所以,在字典中就不要什么索引和切片了。

dict中的這類以鍵值對(duì)的映射方式存儲(chǔ)數(shù)據(jù),是一種非常高效的方法,比如要讀取值得時(shí)候,如果用列表,python需要從頭開始讀,直到找到指定的那個(gè)索引值。但是,在dict中是通過“鍵”來(lái)得到值。要高效得多。 正是這個(gè)特點(diǎn),鍵值對(duì)這樣的形式可以用來(lái)存儲(chǔ)大規(guī)模的數(shù)據(jù),因?yàn)闄z索快捷。規(guī)模越大越明顯。所以,mongdb這種非關(guān)系型數(shù)據(jù)庫(kù)在大數(shù)據(jù)方面比較流行了。

基本操作

字典雖然跟列表有很大的區(qū)別,但是依然有不少類似的地方。它的基本操作:

  • len(d),返回字典(d)中的鍵值對(duì)的數(shù)量
  • d[key],返回字典(d)中的鍵(key)的值
  • d[key]=value,將值(value)賦給字典(d)中的鍵(key)
  • del d[key],刪除字典(d)的鍵(key)項(xiàng)(將該鍵值對(duì)刪除)
  • key in d,檢查字典(d)中是否含有鍵為key的項(xiàng)

下面依次進(jìn)行演示。

>>> city_code
{'suzhou': '0512', 'beijing': '011', 'shanghai': '012', 'tangshan': '0315'}
>>> len(city_code)
4

以city_code為操作對(duì)象,len(city_code)的值是4,表明有四組鍵值對(duì),也可以說(shuō)是四項(xiàng)。

>>> city_code["nanjing"] = "025"
>>> city_code
{'suzhou': '0512', 'beijing': '011', 'shanghai': '012', 'tangshan': '0315', 'nanjing': '025'}

向其中增加一項(xiàng)

>>> city_code["beijing"] = "010"
>>> city_code
{'suzhou': '0512', 'beijing': '010', 'shanghai': '012', 'tangshan': '0315', 'nanjing': '025'}

突然發(fā)現(xiàn)北京的區(qū)號(hào)寫錯(cuò)了??梢赃@樣修改。這進(jìn)一步說(shuō)明字典是可變的。

>>> city_code["shanghai"]
'012'
>>> del city_code["shanghai"]

通過city_code["shanghai"]能夠查看到該鍵(key)所對(duì)應(yīng)的值(value),結(jié)果發(fā)現(xiàn)也錯(cuò)了。干脆刪除,用del,將那一項(xiàng)都刪掉。

>>> city_code["shanghai"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'shanghai'
>>> "shanghai" in city_code
False

因?yàn)殒I是"shanghai"的那個(gè)鍵值對(duì)項(xiàng)已經(jīng)刪除了,隨意不能找到,用in來(lái)看看,返回的是False。

>>> city_code
{'suzhou': '0512', 'beijing': '010', 'tangshan': '0315', 'nanjing': '025'}

真的刪除了哦。沒有了。

字符串格式化輸出

這是一個(gè)前面已經(jīng)探討過的話題,請(qǐng)參看《字符串(4)》,這里再次提到,就是因?yàn)橛米值湟部梢詫?shí)現(xiàn)格式化字符串的目的。雖然在《字符串(4)》那節(jié)中已經(jīng)有了簡(jiǎn)單演示,但是我還是愿意重復(fù)一下。

>>> city_code = {"suzhou":"0512", "tangshan":"0315", "hangzhou":"0571"}
>>> " Suzhou is a beautiful city, its area code is %(suzhou)s" % city_code
' Suzhou is a beautiful city, its area code is 0512'

這種寫法是非常簡(jiǎn)潔,而且很有意思的。有人說(shuō)它簡(jiǎn)直是酷。

其實(shí),更酷還是下面的——模板

在做網(wǎng)頁(yè)開發(fā)的時(shí)候,通常要用到模板,也就是你只需要寫好HTML代碼,然后將某些部位空出來(lái),等著python后臺(tái)提供相應(yīng)的數(shù)據(jù)即可。當(dāng)然,下面所演示的是玩具代碼,基本沒有什么使用價(jià)值,因?yàn)樵谡鎸?shí)的網(wǎng)站開發(fā)中,這樣的姿勢(shì)很少用上。但是,它絕非花拳繡腿,而是你能夠明了其本質(zhì),至少了解到一種格式化方法的應(yīng)用。

>>> temp = "<html><head><title>%(lang)s<title><body><p>My name is %(name)s.</p></body></head></html>"
>>> my = {"name":"qiwsir", "lang":"python"}
>>> temp % my
'<html><head><title>python<title><body><p>My name is qiwsir.</p></body></head></html>'

temp就是所謂的模板,在雙引號(hào)所包裹的實(shí)質(zhì)上是一段HTML代碼。然后在dict中寫好一些數(shù)據(jù),按照模板的要求在相應(yīng)位置顯示對(duì)應(yīng)的數(shù)據(jù)。

是不是一個(gè)很有意思的屠龍之技?

什么是HTML? 下面是在《維基百科》上抄錄的:

超文本標(biāo)記語(yǔ)言(英文:HyperText Markup Language,HTML)是為「網(wǎng)頁(yè)創(chuàng)建和其它可在網(wǎng)頁(yè)瀏覽器中看到的信息」設(shè)計(jì)的一種標(biāo)記語(yǔ)言。HTML被用來(lái)結(jié)構(gòu)化信息——例如標(biāo)題、段落和列表等等,也可用來(lái)在一定程度上描述文檔的外觀和語(yǔ)義。1982年由蒂姆·伯納斯-李創(chuàng)建,由IETF用簡(jiǎn)化的SGML(標(biāo)準(zhǔn)通用標(biāo)記語(yǔ)言)語(yǔ)法進(jìn)行進(jìn)一步發(fā)展的HTML,后來(lái)成為國(guó)際標(biāo)準(zhǔn),由萬(wàn)維網(wǎng)聯(lián)盟(W3C)維護(hù)。

HTML經(jīng)過發(fā)展,現(xiàn)在已經(jīng)到HTML5了。現(xiàn)在的HTML設(shè)計(jì),更強(qiáng)調(diào)“響應(yīng)式”設(shè)計(jì),就是能夠兼顧PC、手機(jī)和各種PAD的不同尺寸的顯示器瀏覽。如果要開發(fā)一個(gè)網(wǎng)站,一定要做到“響應(yīng)式”設(shè)計(jì),否則就只能在PC上看,在手機(jī)上看就不得不左右移動(dòng)。

知識(shí)

什么是關(guān)聯(lián)數(shù)組?以下解釋來(lái)自維基百科

在計(jì)算機(jī)科學(xué)中,關(guān)聯(lián)數(shù)組(英語(yǔ):Associative Array),又稱映射(Map)、字典(Dictionary)是一個(gè)抽象的數(shù)據(jù)結(jié)構(gòu),它包含著類似于(鍵,值)的有序?qū)?。一個(gè)關(guān)聯(lián)數(shù)組中的有序?qū)梢灾貜?fù)(如C++中的multimap)也可以不重復(fù)(如C++中的map)。

這種數(shù)據(jù)結(jié)構(gòu)包含以下幾種常見的操作:

1.向關(guān)聯(lián)數(shù)組添加配對(duì) 2.從關(guān)聯(lián)數(shù)組內(nèi)刪除配對(duì) 3.修改關(guān)聯(lián)數(shù)組內(nèi)的配對(duì) 4.根據(jù)已知的鍵尋找配對(duì)

字典問題是設(shè)計(jì)一種能夠具備關(guān)聯(lián)數(shù)組特性的數(shù)據(jù)結(jié)構(gòu)。解決字典問題的常用方法,是利用散列表,但有些情況下,也可以直接使用有地址的數(shù)組,或二叉樹,和其他結(jié)構(gòu)。

許多程序設(shè)計(jì)語(yǔ)言內(nèi)置基本的數(shù)據(jù)類型,提供對(duì)關(guān)聯(lián)數(shù)組的支持。而Content-addressable memory則是硬件層面上實(shí)現(xiàn)對(duì)關(guān)聯(lián)數(shù)組的支持。

什么是哈希表?關(guān)于哈希表的敘述比較多,這里僅僅截取了概念描述,更多的可以到維基百科上閱讀。

散列表(Hash table,也叫哈希表),是根據(jù)關(guān)鍵字(Key value)而直接訪問在內(nèi)存存儲(chǔ)位置的數(shù)據(jù)結(jié)構(gòu)。也就是說(shuō),它通過把鍵值通過一個(gè)函數(shù)的計(jì)算,映射到表中一個(gè)位置來(lái)訪問記錄,這加快了查找速度。這個(gè)映射函數(shù)稱做散列函數(shù),存放記錄的數(shù)組稱做散列表。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)