字典(1)

2018-02-24 15:48 更新

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

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

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

這種方法能夠快捷的找到目標。

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

假設一種需要,要存儲城市和電話區(qū)號,蘇州的區(qū)號是0512,唐山的是0315,北京的是011,上海的是012。用前面已經(jīng)學習過的知識,可以這么來做:

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

用一個列表來存儲城市名稱,然后用另外一個列表,一一對應地保存區(qū)號。假如要輸出蘇州的區(qū)號,可以這么做:

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

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

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

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

這樣來看,用兩個列表分別來存儲城市和區(qū)號,似乎能夠解決問題。但是,這不是最好的選擇,至少在python里面。因為python還提供了另外一種方案,那就是字典(dict)。

創(chuàng)建dict

方法1:

創(chuàng)建一個空的dict,這個空dict,可以在以后向里面加東西用。

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

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

創(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",有一個優(yōu)雅的名字:鍵值對。前面的name叫做鍵(key),后面的qiwsir是前面的鍵所對應的值(value)。在一個dict中,鍵是唯一的,不能重復。值則是對應于鍵,值可以重復。鍵值之間用(:)英文的分號,每一對鍵值之間用英文的逗號(,)隔開。

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

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

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

實驗表明,字典可以原地修改,即它是可變的。

方法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:

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

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

需要提醒的是,這種方法是重新建立一個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ù)類型是以鍵值對的形式存儲數(shù)據(jù)的,所以,只要知道鍵,就能得到值。這本質(zhì)上就是一種映射關系。

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

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

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

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

本節(jié)開頭那個城市和區(qū)號的關系,也可以用字典來存儲和讀取。

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

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

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

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

在list中,得到值是用索引的方法。那么在字典中有索引嗎?當然沒有,因為它沒有順序,哪里來的索引呢?所以,在字典中就不要什么索引和切片了。

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

基本操作

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

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

下面依次進行演示。

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

以city_code為操作對象,len(city_code)的值是4,表明有四組鍵值對,也可以說是四項。

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

向其中增加一項

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

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

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

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

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

因為鍵是"shanghai"的那個鍵值對項已經(jīng)刪除了,隨意不能找到,用in來看看,返回的是False。

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

真的刪除了哦。沒有了。

字符串格式化輸出

這是一個前面已經(jīng)探討過的話題,請參看《字符串(4)》,這里再次提到,就是因為用字典也可以實現(xiàn)格式化字符串的目的。雖然在《字符串(4)》那節(jié)中已經(jīng)有了簡單演示,但是我還是愿意重復一下。

>>> 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'

這種寫法是非常簡潔,而且很有意思的。有人說它簡直是酷。

其實,更酷還是下面的——模板

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

>>> 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就是所謂的模板,在雙引號所包裹的實質(zhì)上是一段HTML代碼。然后在dict中寫好一些數(shù)據(jù),按照模板的要求在相應位置顯示對應的數(shù)據(jù)。

是不是一個很有意思的屠龍之技?

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

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

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

知識

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

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

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

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

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

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

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

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

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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號