- 零基礎(chǔ)入門學(xué)習(xí)Python(第2版)
- 小甲魚
- 3360字
- 2019-12-20 12:19:43
第7章 字典和集合
7.1 字典:當(dāng)索引不好用時(shí)

視頻講解

圖7-1 映射
有一天你想翻開《新華字典》,查找一下“龜”是不是一種鳥。如果是按拼音檢索,你總不可能從字母a開始查找吧?而應(yīng)該直接翻到字母g在字典中的位置,然后接著找到gui的發(fā)音,繼而找到“龜”字的釋義:廣義上指龜鱉目的統(tǒng)稱,狹義上指龜科下的物種。
在Python中也有字典,就拿剛才的例子來說,Python的字典把這個(gè)字(或單詞)稱為“鍵(key)”,把其對(duì)應(yīng)的含義稱為“值(value)”。另外值得一提的是,Python的字典在有些地方稱為哈希(hash),有些地方稱為關(guān)系數(shù)組,其實(shí)這些都與今天要講的Python字典是同一個(gè)概念。
字典是Python中唯一的映射類型,映射是數(shù)學(xué)上的一個(gè)術(shù)語,指兩個(gè)元素集之間元素相互“對(duì)應(yīng)”的關(guān)系,如圖7-1所示。
映射類型區(qū)別于序列類型,序列類型以數(shù)組的形式存儲(chǔ),通過索引的方式來獲取相應(yīng)位置的值,一般索引值與對(duì)應(yīng)位置存儲(chǔ)的數(shù)據(jù)是毫無關(guān)系的。
舉個(gè)例子:
>>> brand = ["李寧", "耐克", "阿迪達(dá)斯", "魚C工作室"] >>> slogan = ["一切皆有可能", "Just do it", "Impossible is nothing", "讓 編程改變世界"] >>> print("魚C工作室的口號(hào)是:%s" % slogan[brand.index("魚C工作室")]) 魚C工作室的口號(hào)是:讓編程改變世界
列表brand、slogan的索引和相對(duì)的值是沒有任何關(guān)系的,可以看出,在兩個(gè)列表間,索引號(hào)相同的元素是有關(guān)系的(品牌對(duì)應(yīng)口號(hào)),所以這里通過“brand.index('魚C工作室')”這樣的語句,間接地實(shí)現(xiàn)通過品牌查找對(duì)應(yīng)的口號(hào)的功能。
這確實(shí)是一種可實(shí)現(xiàn)方法,但用起來多少有些別扭,而且效率還不高。況且Python是以簡潔為主,這樣的實(shí)現(xiàn)肯定是差強(qiáng)人意的。
7.1.1 創(chuàng)建和訪問字典
先演示一下用法:

字典的使用非常簡單,它有自己的標(biāo)志性符號(hào),就是用大括號(hào)({})定義。字典由“鍵”和“值”共同構(gòu)成,每一對(duì)鍵值組合稱為“項(xiàng)”。
在剛才的例子中,李寧、耐克、阿迪達(dá)斯、魚C工作室這些品牌就是鍵,而一切皆有可能、Just do it、Impossible is nothing、讓編程改變世界,這些口號(hào)就是對(duì)應(yīng)的值。
注意:
字典的鍵必須獨(dú)一無二,但值則不必。值可以取任何數(shù)據(jù)類型,但必須是不可變的,如字符串、數(shù)或元組。
要聲明一個(gè)空字典,直接用大括號(hào)即可:
>>> empty = {} >>> empty {} >>> type(empty) <class 'dict'>
也可以使用dict()內(nèi)置函數(shù)來創(chuàng)建字典:
>>> dict1 = dict((('F', 70), ('i', 105), ('s', 115), ('h', 104), ('C', 67))) >>> dict1 {'F': 70, 'i': 105, 's': 115, 'h': 104, 'C': 67}
有讀者可能會(huì)問,為什么上面的例子中出現(xiàn)這么多小括號(hào)?
因?yàn)閐ict()函數(shù)的參數(shù)可以是一個(gè)序列(但不能是多個(gè)),所以要打包成一個(gè)元組(或列表)序列。
當(dāng)然,如果嫌上面的做法太麻煩,還可以通過提供具有映射關(guān)系的參數(shù)來創(chuàng)建字典:
>>> dict1 = dict(F=70, i=105, s=115, h=104, C=67) >>> dict1 {'F': 70, 'i': 105, 's': 115, 'h': 104, 'C': 67}
這里要注意的是,鍵的位置不能加上表示字符串的引號(hào),否則會(huì)報(bào)錯(cuò):
>>> dict1 = dict('F'=70, 'i'=105, 's'=115, 'h'=104, 'C'=67) SyntaxError: keyword can't be an expression
訪問字典里的值與訪問序列類似,只需要把相應(yīng)的鍵放入方括號(hào)即可,如果該鍵不在映射中,則拋出KeyError:

還有一種創(chuàng)建方法是直接給字典的鍵賦值,如果鍵已存在,則改寫鍵對(duì)應(yīng)的值;如果鍵不存在,則創(chuàng)建一個(gè)新的鍵并賦值:
>>> dict1 {'F': 70, 'i': 105, 's': 115, 'h': 104, 'C': 67} >>> dict1['x'] = 88 >>> dict1 {'F': 70, 'i': 105, 's': 115, 'h': 104, 'C': 67, 'x': 88} >>> dict1['x'] = 120 >>> dict1 {'F': 70, 'i': 105, 's': 115, 'h': 104, 'C': 67, 'x': 120}
注意:
字典不允許同一個(gè)鍵出現(xiàn)兩次,如果同一個(gè)鍵被賦值兩次,后一個(gè)值會(huì)被記住:
>>> courses = {"小甲魚":"《零基礎(chǔ)入門學(xué)習(xí)Python》", "不二如是":"《零基礎(chǔ)入門學(xué) 習(xí)Scratch》", "小甲魚":"《極客Python之效率革命》"} >>> courses {'小甲魚': '《極客Python之效率革命》','不二如是': '《零基礎(chǔ)入門學(xué)習(xí)Scratch》'}
鍵必須不可變,所以可以用數(shù)值、字符串或元組充當(dāng),如果使用列表那就不行了:

正所謂殊途同歸,下面列舉的五種方法都是創(chuàng)建同樣的字典,大家仔細(xì)體會(huì)一下:
>>> a = dict(one=1, two=2, three=3) >>> b = {'one': 1, 'two': 2, 'three': 3} >>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3])) >>> d = dict([('two', 2), ('one', 1), ('three', 3)]) >>> e = dict({'three': 3, 'one': 1, 'two': 2}) >>> a == b == c == d == e True
有別于序列,字典是不支持拼接和重復(fù)操作的:

7.1.2 各種內(nèi)置方法

視頻講解
1)fromkeys(seq[, value])
fromkeys()方法用于創(chuàng)建并返回一個(gè)新的字典,它有兩個(gè)參數(shù);第一個(gè)參數(shù)是字典的鍵;第二個(gè)參數(shù)是可選的,是傳入鍵對(duì)應(yīng)的值,如果不提供,那么默認(rèn)是None。
舉個(gè)例子:
>>> dict1 = {} >>> dict1.fromkeys((1, 2, 3)) {1: None, 2: None, 3: None} >>> dict2 = {} >>> dict2.fromkeys((1, 2, 3), "Number") {1: 'Number', 2: 'Number', 3: 'Number'} >>> dict3 = {} >>> dict3.fromkeys((1, 2, 3), ("one", "two", "three")) {1: ('one', 'two', 'three'), 2: ('one', 'two', 'three'), 3: ('one', 'two', 'three')}
上面最后一個(gè)例子告訴我們做事不能總是想當(dāng)然,有時(shí)候現(xiàn)實(shí)會(huì)給你狠狠的一棒。fromkeys()方法并不會(huì)將值"one"、"two"和"three"分別賦值鍵1、2和3,因?yàn)閒romkeys()把("one", "two", "three")當(dāng)成一個(gè)值了。
2)keys(),values()和items()
訪問字典的方法有keys()、values()和items()。keys()用于返回字典中的鍵,values()用于返回字典中所有的值,那么,items()當(dāng)然就是返回字典中所有的鍵值對(duì)(也就是項(xiàng))。
舉個(gè)例子:
>>> dict1 = {} >>> dict1 = dict1.fromkeys(range(32), "贊") >>> dict1.keys() dict_keys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]) >>> dict1.values() dict_values(['贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊', '贊']) >>> dict1.items() dict_items([(0, '贊'), (1, '贊'), (2, '贊'), (3, '贊'), (4, '贊'), (5, '贊'), (6, '贊'), (7, '贊'), (8, '贊'), (9, '贊'), (10, '贊'), (11, '贊'), (12, '贊'), (13, '贊'), (14, '贊'), (15, '贊'), (16, '贊'), (17, '贊'), (18, '贊'), (19, '贊'), (20, '贊'), (21, '贊'), (22, '贊'), (23, '贊'), (24, '贊'), (25, '贊'), (26, '贊'), (27, '贊'), (28, '贊'), (29, '贊'), (30, '贊'), (31, '贊')])
字典可以很大,有時(shí)候我們并不知道提供的項(xiàng)是否在字典中存在,如果不存在,Python就會(huì)報(bào)錯(cuò):

對(duì)于代碼調(diào)試階段,報(bào)錯(cuò)可以讓程序員及時(shí)發(fā)現(xiàn)程序存在的問題并修改。但是如果程序已經(jīng)發(fā)布了,那么經(jīng)常報(bào)錯(cuò)的程序肯定是會(huì)被用戶遺棄的。
3)get(key[, default])
get()方法提供了更寬松的方式去訪問字典項(xiàng),當(dāng)鍵不存在的時(shí)候,get()方法并不會(huì)報(bào)錯(cuò),只是默默地返回了一個(gè)None,表示啥都沒找到:
>>> dict1.get(31) '贊' >>> dict1.get(32) >>>
如果希望找不到數(shù)據(jù)時(shí)返回指定的值,那么可以在第二個(gè)參數(shù)設(shè)置對(duì)應(yīng)的默認(rèn)返回值:
>>> dict1.get(32, "木有") '木有'
如果不知道一個(gè)鍵是否在字典中,那么可以使用成員資格操作符(in或not in)來判斷:
>>> 31 in dict1 True >>> 32 in dict2 False
在字典中檢查鍵的成員資格比序列更高效,當(dāng)數(shù)據(jù)規(guī)模相當(dāng)大的時(shí)候,兩者的差距會(huì)很明顯(注:因?yàn)樽值涫遣捎霉7椒ㄒ粚?duì)一找到成員,而序列則是采取迭代的方式逐個(gè)比對(duì))。最后要注意的一點(diǎn)是,這里查找的是鍵而不是值,但是在序列中查找的是元素的值而不是元素的索引。
如果需要清空一個(gè)字典,則使用clear()方法:
>>> dict1 {0: '贊', 1: '贊', 2: '贊', 3: '贊', 4: '贊', 5: '贊', 6: '贊', 7: '贊', 8: '贊', 9: '贊', 10: '贊', 11: '贊', 12: '贊', 13: '贊', 14: '贊', 15: '贊', 16: '贊', 17: '贊', 18: '贊', 19: '贊', 20: '贊', 21: '贊', 22: '贊', 23: '贊', 24: '贊', 25: '贊', 26: '贊', 27: '贊', 28: '贊', 29: '贊', 30: '贊', 31: '贊'} >>> dict1.clear() >>> dict1 {}
有的讀者可能會(huì)使用變量名賦值為一個(gè)空字典的方法來清空字典,這樣的做法其實(shí)存在一定的弊端。
下面給大家解釋這兩種清除方法有什么不同。
>>> a = {"姓名":"小甲魚", "密碼":"123456"} >>> b = a >>> b {'姓名': '小甲魚', '密碼': '123456'} >>> a = {} >>> a {} >>> b {'姓名': '小甲魚', '密碼': '123456'}
從上面的例子中可以看到,a、b指向同一個(gè)字典,然后試圖通過將a重新指向一個(gè)空字典來達(dá)到清空的效果時(shí),我們發(fā)現(xiàn)原來的字典并沒有被真正清空,只是a指向了一個(gè)新的空字典而已。所以,這種做法在一定條件下會(huì)留下安全隱患(例如,賬戶的數(shù)據(jù)和密碼等資料有可能會(huì)被竊取)。
推薦的做法是使用clear()方法:
>>> a = {"姓名":"小甲魚", "密碼":"123456"} >>> b = a >>> b {'姓名': '小甲魚', '密碼': '123456'} >>> a.clear() >>> a {} >>> b {}
4)copy()
copy()方法是用于拷貝(淺拷貝)整個(gè)字典:
>>> a = {1:"one", 2:"two", 3:"three"} >>> b = a.copy() >>> id(a) 63239624 >>> id(b) 63239688 >>> a[1] = "four" >>> a {1: 'four', 2: 'two', 3: 'three'} >>> b {1: 'one', 2: 'two', 3: 'three'}
5)pop(key[, default])和popitem()
pop()是給定鍵彈出對(duì)應(yīng)的值,而popitem()是彈出一個(gè)項(xiàng),這兩個(gè)比較容易理解:
>>> a = {1:"one", 2:"two", 3:"three", 4:"four"} >>> a.pop(2) 'two' >>> a {1: 'one', 3: 'three', 4: 'four'} >>> a.popitem() (1, 'one') >>> a {3: 'three', 4: 'four'}
6)setdefault(key[, default])
setdefault()方法和get()方法有點(diǎn)相似,但是,setdefault()在字典中找不到相應(yīng)的鍵時(shí)會(huì)自動(dòng)添加:
>>> a = {1:"one", 2:"two", 3:"three", 4:"four"} >>> a.setdefault(3) 'three' >>> a.setdefault(5) >>> a {1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: None}
7)update([other])
最后一個(gè)是update()方法,可以利用它來更新字典:
>>> pets = {"米奇":"老鼠", "湯姆":"貓", "小白":"豬"} >>> pets.update(小白="狗") >>> pets {'米奇': '老鼠', '湯姆': '貓', '小白': '狗'}
還記得在6.2節(jié)的末尾我們埋下了一個(gè)伏筆,在講到收集參數(shù)的時(shí)候,我們說Python還有另一種收集方式,就是用兩個(gè)星號(hào)(**)表示。兩個(gè)星號(hào)的收集參數(shù)表示為將參數(shù)們打包成字典的形式,現(xiàn)在講到了字典,就順理成章地給大家講講吧。
收集參數(shù)其實(shí)有兩種打包形式:一種是以元組的形式打包;另一種則是以字典的形式打包。

當(dāng)參數(shù)帶兩個(gè)星號(hào)(**)時(shí),傳遞給函數(shù)的任意數(shù)量的key=value實(shí)參會(huì)被打包進(jìn)一個(gè)字典中。那么有打包就有解包,再來看下一個(gè)例子:
>>> a = {"one":1, "two":2, "three":3} >>> test(**a) 有 3 個(gè)參數(shù) 它們分別是: {'three': 3, 'one': 1, 'two': 2}
- Practical Data Analysis Cookbook
- Vue.js 2 and Bootstrap 4 Web Development
- HTML5+CSS3+JavaScript Web開發(fā)案例教程(在線實(shí)訓(xùn)版)
- 從Excel到Python:用Python輕松處理Excel數(shù)據(jù)(第2版)
- C語言程序設(shè)計(jì)同步訓(xùn)練與上機(jī)指導(dǎo)(第三版)
- Java圖像處理:基于OpenCV與JVM
- SQL Server 2008 R2數(shù)據(jù)庫技術(shù)及應(yīng)用(第3版)
- Python數(shù)據(jù)可視化之美:專業(yè)圖表繪制指南(全彩)
- 深入實(shí)踐DDD:以DSL驅(qū)動(dòng)復(fù)雜軟件開發(fā)
- Ext JS 4 Plugin and Extension Development
- 跟小樓老師學(xué)用Axure RP 9:玩轉(zhuǎn)產(chǎn)品原型設(shè)計(jì)
- INSTANT Lift Web Applications How-to
- 信息安全技術(shù)(第2版)
- 自然語言處理NLP從入門到項(xiàng)目實(shí)戰(zhàn):Python語言實(shí)現(xiàn)
- Java從入門到精通(微視頻精編版)