字典,這個東西你現在還用嗎?隨著網絡的發展,用的人越來越少了。不少人習慣于在網上搜索,不僅有web版,乃至于已經有手機版的各種字典了。我在上小學的時候曾經用過一本小小的《新華字典》,記得是拾了不少廢品,然后換錢,最終花費了1.01元人民幣買的。
> 《新華字典》是中國第一部現代漢語字典。最早的名字叫《伍記小字典》,但未能編纂完成。自1953年,開始重編,其凡例完全采用《伍記小字典》。從1953年開始出版,經過反復修訂,但是以1957年商務印書館出版的《新華字典》作為第一版。原由新華辭書社編寫,1956年并入中科院語言研究所(現中國社科院語言研究所)詞典編輯室。新華字典由商務印書館出版。歷經幾代上百名專家學者10余次大規模的修訂,重印200多次。成為迄今為止世界出版史上最高發行量的字典。
這里講到字典,不是為了回憶青蔥歲月。而是提醒看官想想我們如何使用字典:先查索引(不管是拼音還是偏旁查字),然后通過索引找到相應內容。不用從頭開始一頁一頁地找。
這種方法能夠快捷的找到目標。
正是基于這種需要,python中有了一種叫做dictionary的數據類型,翻譯過來就是“字典”,用dict表示。
假設一種需要,要存儲城市和電話區號,蘇州的區號是0512,唐山的是0315,北京的是011,上海的是012。用前面已經學習過的知識,可以這么來做:
~~~
>>> citys = ["suzhou", "tangshan", "beijing", "shanghai"]
>>> city_codes = ["0512", "0315", "011", "012"]
~~~
用一個列表來存儲城市名稱,然后用另外一個列表,一一對應地保存區號。假如要輸出蘇州的區號,可以這么做:
~~~
>>> print "{} : {}".format(citys[0], city_codes[0])
suzhou : 0512
~~~
> 請特別注意,我在city_codes中,表示區號的元素沒有用整數型,而是使用了字符串類型,你知道為什么嗎? 如果用整數,就是這樣的。
~~~
>>> suzhou_code = 0512
>>> print suzhou_code
330
~~~
> 怎么會這樣?原來在python中,如果按照上面那樣做,0512并沒有被認為是一個八進制的數,用print打印的時候,將它轉換為了十進制輸出。關于進制轉換問題,看官可以網上搜索一下有關資料。此處不詳述。一般是用幾個內建函數實現:`int()`,?`bin()`,?`oct()`,?`hex()`
這樣來看,用兩個列表分別來存儲城市和區號,似乎能夠解決問題。但是,這不是最好的選擇,至少在python里面。因為python還提供了另外一種方案,那就是字典(dict)。
## [](https://github.com/qiwsir/StarterLearningPython/blob/master/116.md#創建dict)創建dict
**方法1:**
創建一個空的dict,這個空dict,可以在以后向里面加東西用。
~~~
>>> mydict = {}
>>> mydict
{}
~~~
不要小看“空”,“色即是空,空即是色”,在編程中,“空”是很重要。一般帶“空”字的人都很有名,比如孫悟空,哦。好像他應該是猴、或者是神。舉一個人的名字,帶“空”字,你懂得。
創建有內容的dict。
~~~
>>> person = {"name":"qiwsir","site":"qiwsir.github.io","language":"python"}
>>> person
{'name': 'qiwsir', 'language': 'python', 'site': 'qiwsir.github.io'}
~~~
`"name":"qiwsir"`,有一個優雅的名字:鍵值對。前面的name叫做鍵(key),后面的qiwsir是前面的鍵所對應的值(value)。在一個dict中,鍵是唯一的,不能重復。值則是對應于鍵,值可以重復。鍵值之間用(:)英文的分號,每一對鍵值之間用英文的逗號(,)隔開。
~~~
>>> person['name2']="qiwsir" #這是一種向dict中增加鍵值對的方法
>>> person
{'name2': 'qiwsir', 'name': 'qiwsir', 'language': 'python', 'site': 'qiwsir.github.io'}
~~~
用這樣的方法可以向一個dict類型的數據中增加“鍵值對”,也可以說是增加數值。那么,增加了值之后,那個字典還是原來的嗎?也就是也要同樣探討一下,字典是否能原地修改?(列表可以,所以列表是可變的;字符串和元組都不行,所以它們是不可變的。)
~~~
>>> ad = {}
>>> id(ad)
3072770636L
>>> ad["name"] = "qiwsir"
>>> ad
{'name': 'qiwsir'}
>>> id(ad)
3072770636L
~~~
實驗表明,字典可以原地修改,即它是可變的。
**方法2:**
利用元組在建構字典,方法如下:
~~~
>>> 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。
需要提醒注意的是,在字典中的“鍵”,必須是不可變的數據類型;“值”可以是任意數據類型。
~~~
>>> 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'
~~~
## [](https://github.com/qiwsir/StarterLearningPython/blob/master/116.md#訪問dict的值)訪問dict的值
dict數據類型是以鍵值對的形式存儲數據的,所以,只要知道鍵,就能得到值。這本質上就是一種映射關系。
> 映射,就好比“物體”和“影子”的關系,“形影相吊”,兩者之間是映射關系。此外,映射也是一個嚴格數學概念: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中的“值”。
本節開頭那個城市和區號的關系,也可以用字典來存儲和讀取。
~~~
>>> 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中的這類以鍵值對的映射方式存儲數據,是一種非常高效的方法,比如要讀取值得時候,如果用列表,python需要從頭開始讀,直到找到指定的那個索引值。但是,在dict中是通過“鍵”來得到值。要高效得多。 正是這個特點,鍵值對這樣的形式可以用來存儲大規模的數據,因為檢索快捷。規模越大越明顯。所以,mongdb這種非關系型數據庫在大數據方面比較流行了。
## [](https://github.com/qiwsir/StarterLearningPython/blob/master/116.md#基本操作)基本操作
字典雖然跟列表有很大的區別,但是依然有不少類似的地方。它的基本操作:
* len(d),返回字典(d)中的鍵值對的數量
* 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'}
~~~
突然發現北京的區號寫錯了。可以這樣修改。這進一步說明字典是可變的。
~~~
>>> city_code["shanghai"]
'012'
>>> del city_code["shanghai"]
~~~
通過`city_code["shanghai"]`能夠查看到該鍵(key)所對應的值(value),結果發現也錯了。干脆刪除,用del,將那一項都刪掉。
~~~
>>> city_code["shanghai"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'shanghai'
>>> "shanghai" in city_code
False
~~~
因為鍵是"shanghai"的那個鍵值對項已經刪除了,隨意不能找到,用`in`來看看,返回的是`False`。
~~~
>>> city_code
{'suzhou': '0512', 'beijing': '010', 'tangshan': '0315', 'nanjing': '025'}
~~~
真的刪除了哦。沒有了。
## [](https://github.com/qiwsir/StarterLearningPython/blob/master/116.md#字符串格式化輸出)字符串格式化輸出
這是一個前面已經探討過的話題,請參看[《字符串(4)》](https://github.com/qiwsir/StarterLearningPython/blob/master/109),這里再次提到,就是因為用字典也可以實現格式化字符串的目的。雖然在《字符串(4)》那節中已經有了簡單演示,但是我還是愿意重復一下。
~~~
>>> 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'
~~~
這種寫法是非常簡潔,而且很有意思的。有人說它簡直是酷。
其實,更酷還是下面的——模板
在做網頁開發的時候,通常要用到模板,也就是你只需要寫好HTML代碼,然后將某些部位空出來,等著python后臺提供相應的數據即可。當然,下面所演示的是玩具代碼,基本沒有什么使用價值,因為在真實的網站開發中,這樣的姿勢很少用上。但是,它絕非花拳繡腿,而是你能夠明了其本質,至少了解到一種格式化方法的應用。
~~~
>>> 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就是所謂的模板,在雙引號所包裹的實質上是一段HTML代碼。然后在dict中寫好一些數據,按照模板的要求在相應位置顯示對應的數據。
是不是一個很有意思的屠龍之技?
> 什么是HTML? 下面是在《維基百科》上抄錄的:
>
> 超文本標記語言(英文:HyperText Markup Language,HTML)是為「網頁創建和其它可在網頁瀏覽器中看到的信息」設計的一種標記語言。HTML被用來結構化信息——例如標題、段落和列表等等,也可用來在一定程度上描述文檔的外觀和語義。1982年由蒂姆·伯納斯-李創建,由IETF用簡化的SGML(標準通用標記語言)語法進行進一步發展的HTML,后來成為國際標準,由萬維網聯盟(W3C)維護。
>
> HTML經過發展,現在已經到HTML5了。現在的HTML設計,更強調“響應式”設計,就是能夠兼顧PC、手機和各種PAD的不同尺寸的顯示器瀏覽。如果要開發一個網站,一定要做到“響應式”設計,否則就只能在PC上看,在手機上看就不得不左右移動。
## [](https://github.com/qiwsir/StarterLearningPython/blob/master/116.md#知識)知識
什么是關聯數組?以下解釋來自[維基百科](http://zh.wikipedia.org/wiki/%E5%85%B3%E8%81%94%E6%95%B0%E7%BB%84)
> 在計算機科學中,關聯數組(英語:Associative Array),又稱映射(Map)、字典(Dictionary)是一個抽象的數據結構,它包含著類似于(鍵,值)的有序對。一個關聯數組中的有序對可以重復(如C++中的multimap)也可以不重復(如C++中的map)。
>
> 這種數據結構包含以下幾種常見的操作:
>
> > 1.向關聯數組添加配對 2.從關聯數組內刪除配對 3.修改關聯數組內的配對 4.根據已知的鍵尋找配對
>
> 字典問題是設計一種能夠具備關聯數組特性的數據結構。解決字典問題的常用方法,是利用散列表,但有些情況下,也可以直接使用有地址的數組,或二叉樹,和其他結構。
>
> 許多程序設計語言內置基本的數據類型,提供對關聯數組的支持。而Content-addressable memory則是硬件層面上實現對關聯數組的支持。
什么是哈希表?關于哈希表的敘述比較多,這里僅僅截取了概念描述,更多的可以到[維基百科上閱讀](http://zh.wikipedia.org/wiki/%E5%93%88%E5%B8%8C%E8%A1%A8)。
> 散列表(Hash table,也叫哈希表),是根據關鍵字(Key value)而直接訪問在內存存儲位置的數據結構。也就是說,它通過把鍵值通過一個函數的計算,映射到表中一個位置來訪問記錄,這加快了查找速度。這個映射函數稱做散列函數,存放記錄的數組稱做散列表。
- 第零章 預備
- 關于Python的故事
- 從小工到專家
- Python安裝
- 集成開發環境
- 第壹章 基本數據類型
- 數和四則運算
- 除法
- 常用數學函數和運算優先級
- 寫一個簡單的程序
- 字符串(1)
- 字符串(2)
- 字符串(3)
- 字符串(4)
- 字符編碼
- 列表(1)
- 列表(2)
- 列表(3)
- 回顧list和str
- 元組
- 字典(1)
- 字典(2)
- 集合(1)
- 集合(2)
- 第貳章 語句和文件
- 運算符
- 語句(1)
- 語句(2)
- 語句(3)
- 語句(4)
- 語句(5)
- 文件(1)
- 文件(2)
- 迭代
- 練習
- 自省
- 第叁章 函數
- 函數(1)
- 函數(2)
- 函數(3)
- 函數(4)
- 函數練習
- 第肆章 類
- 類(1)
- 類(2)
- 類(3)
- 類(4)
- 類(5)
- 多態和封裝
- 特殊方法(1)
- 特殊方法(2)
- 迭代器
- 生成器
- 上下文管理器
- 第伍章 錯誤和異常
- 錯誤和異常(1)
- 錯誤和異常(2)
- 錯誤和異常(3)
- 第陸章 模塊
- 編寫模塊
- 標準庫(1)
- 標準庫(2)
- 標準庫(3)
- 標準庫(4)
- 標準庫(5)
- 標準庫(6)
- 標準庫(7)
- 標準庫(8)
- 第三方庫
- 第柒章 保存數據
- 將數據存入文件
- mysql數據庫(1)
- MySQL數據庫(2)
- mongodb數據庫(1)
- SQLite數據庫
- 電子表格
- 第捌章 用Tornado做網站
- 為做網站而準備
- 分析Hello
- 用tornado做網站(1)
- 用tornado做網站(2)
- 用tornado做網站(3)
- 用tornado做網站(4)
- 用tornado做網站(5)
- 用tornado做網站(6)
- 用tornado做網站(7)
- 第玖章 科學計算
- 為計算做準備
- Pandas使用(1)
- Pandas使用(2)
- 處理股票數據
- 附:網絡文摘
- 如何成為Python高手
- ASCII、Unicode、GBK和UTF-8字符編碼的區別聯系