集合是一種很有用的數(shù)學(xué)操作,比如列表去重,或是理清兩組數(shù)據(jù)之間的關(guān)系,集合的操作符和位操作符有交集,注意不要弄混:
A = set([1, 2, 3, 4])
B = {3, 4, 5, 6}
C = set([1, 1, 2, 2, 2, 3, 3, 3, 3])
print(C) # 集合的去重效果,set([1, 2, 3])
print(A | B) # 求并集,set([1, 2, 3, 4, 5, 6])
print(A & B) # 求交集,set([3, 4])
print(A - B) # 求差集,屬于A但不屬于B的,set([1, 2])
print(B - A) # 求差集,屬于B但不屬于A的,set([5, 6])
print(A ^ B) # 求對(duì)稱差集,相當(dāng)于(A-B)|(B-A),set([1, 2, 5, 6])
字典
字典是一種非常常見的“鍵-值”(key-value)映射結(jié)構(gòu),鍵無(wú)重復(fù),一個(gè)鍵不能對(duì)應(yīng)多個(gè)值,不過(guò)多個(gè)鍵可以指向一個(gè)值。還是通過(guò)例子來(lái)了解,構(gòu)建一個(gè)名字->年齡的字典,并執(zhí)行一些常見操作:
a = {'Tom': 8, 'Jerry': 7}
print(a['Tom']) # 8
b = dict(Tom=8, Jerry=7) # 一種字符串作為鍵更方便的初始化方式
print(b['Tom']) # 8
if 'Jerry' in a: # 判斷'Jerry'是否在keys里面
print(a['Jerry']) # 7
print(a.get('Spike')) # None,通過(guò)get獲得值,即使鍵不存在也不會(huì)報(bào)異常
a['Spike'] = 10
a['Tyke'] = 3
a.update({'Tuffy': 2, 'Mammy Two Shoes': 42})
print(a.values()) # dict_values([8, 2, 3, 7, 10, 42])
print(a.pop('Mammy Two Shoes')) # 移除'Mammy Two Shoes'的鍵值對(duì),并返回42
print(a.keys()) # dict_keys(['Tom', 'Tuffy', 'Tyke', 'Jerry', 'Spike'])
注意到初始化字典和集合很像,的確如此,集合就像是沒有值只有鍵的字典。既然有了人名到年齡的映射,也許你立馬想到是否可以給字典排序?在Python3.6之前,這個(gè)問(wèn)題是錯(cuò)誤的,字典是一種映射關(guān)系,沒有順序。當(dāng)然了,如果要把(鍵, 值)的這種對(duì)進(jìn)行排序,是沒有問(wèn)題的,前提是先把字典轉(zhuǎn)化成可排序的結(jié)構(gòu),items()或者iteritems()可以做到這件事,接上段代碼繼續(xù):
b = a.items()
print(b) # [('Tuffy', 2), ('Spike', 10), ('Tom', 8), ('Tyke', 3), ('Jerry', 7)]
from operator import itemgetter
c = sorted(a.items(), key=itemgetter(1))
print(c) # [('Tuffy', 2), ('Tyke', 3), ('Jerry', 7), ('Tom', 8), ('Spike', 10)]
d = sorted(a.iteritems(), key=itemgetter(1))
print(d) # [('Tuffy', 2), ('Tyke', 3), ('Jerry', 7), ('Tom', 8), ('Spike', 10)]
e = sorted(a)
print(e) # 只對(duì)鍵排序,['Jerry', 'Spike', 'Tom', 'Tuffy', 'Tyke']
items()可以把字典中的鍵值對(duì)轉(zhuǎn)化成一個(gè)列表,其中每個(gè)元素是一個(gè)tuple,tuple的第一個(gè)元素是鍵,第二個(gè)元素是值。變量c是按照值排序,所以需要一個(gè)操作符itemgetter,去位置為1的元素作為排序參考,如果直接對(duì)字典排序,則其實(shí)相當(dāng)于只是對(duì)鍵排序。字典被當(dāng)作一個(gè)普通的可遍歷結(jié)構(gòu)使用時(shí),都相當(dāng)于遍歷字典的鍵。如果覺得字典沒有順序不方便,可以考慮使用OrderedDict,使用方式如下:
from collections import OrderedDict
a = {1: 2, 3: 4, 5: 6, 7: 8, 9: 10}
b = OrderedDict({1: 2, 3: 4, 5: 6, 7: 8, 9: 10})
print(a) # {1: 2, 3: 4, 9: 10, 5: 6, 7: 8}
print(b) # OrderedDict([(1, 2), (3, 4), (9, 10), (5, 6), (7, 8)])
這樣初始化時(shí)的順序就保留了,除了有序的特性以外,用法上和字典沒有區(qū)別。2016年9月,Guido宣布在Python3.6中,字典將默認(rèn)有序,這樣就不用糾結(jié)了。另外需要注意的一點(diǎn)是字典是通過(guò)哈希表實(shí)現(xiàn)的,所以鍵必須是可哈希的, list不能被哈希,所以也不能作為字典的鍵,而tuple就可以。
因?yàn)樯仙隙未a中用到了iteritems(),所以這里順帶提一下迭代器(iterator),迭代器相當(dāng)于一個(gè)函數(shù),每次調(diào)用都返回下一個(gè)元素,從遍歷的角度來(lái)看就和列表沒有區(qū)別了。iteritems()就是一個(gè)迭代器,所以效果一樣,區(qū)別是迭代器占用更少內(nèi)存,因?yàn)椴恍枰簧蟻?lái)就生成整個(gè)列表。一般來(lái)說(shuō),如果只需要遍歷一次,用迭代器是更好的選擇,若是要多次頻繁從一個(gè)可遍歷結(jié)構(gòu)中取值,且內(nèi)存夠,則直接生成整個(gè)列表會(huì)更好。當(dāng)然,用迭代器生成一個(gè)完整列表并不麻煩,所以有個(gè)趨勢(shì)是把迭代器作為默認(rèn)的可遍歷方式,比如前面我們使用過(guò)用來(lái)生成等差數(shù)列列表的range(),在Python2中對(duì)應(yīng)的迭代器形式是xrange()。在Python3中,range()就不再產(chǎn)生一個(gè)列表了,而是作為迭代器,xrange()直接沒了。
分支和循環(huán)
從這節(jié)開始,代碼就未必適合在Python終端中輸入了,選個(gè)順手的編輯器或者IDE。作者良心推薦PyCharm,雖然慢,但好用,社區(qū)版免費(fèi):
PyCharm
for循環(huán)
評(píng)論
查看更多