版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第5章字典與集合Python程序設(shè)計(jì)第5章字典與集合Python提供了豐富的序列類型、內(nèi)置函數(shù)、方法以及語法支持等,讓我們能夠輕松運(yùn)用序列形式的容器(數(shù)據(jù)結(jié)構(gòu))對(duì)象。但數(shù)據(jù)并非只有順序的形式,也有“映射”形式的數(shù)據(jù)結(jié)構(gòu),即“字典”,其內(nèi)含元素都是所謂的“鍵值配對(duì)”,從鍵映射到值。第5章字典與集合此外,集合也是常見的數(shù)據(jù)類型,具有嚴(yán)謹(jǐn)?shù)臄?shù)學(xué)定義,可用來存放東西(對(duì)象),但只能放進(jìn)去一次,也就是記錄某東西“在不在”里面。集合既非序列、也非映射,自有其一套機(jī)制,且與字典相關(guān)。有了列表與字典,幾乎就可組合出絕大部分所需的數(shù)據(jù)結(jié)構(gòu)。當(dāng)談到某種數(shù)據(jù)類型時(shí),不外乎學(xué)習(xí)如何建立、存與?。▽懪c讀)、搜尋、排序、分類、過濾等等操作動(dòng)作。關(guān)于雜湊1字典與集合的訪問接口4字典結(jié)構(gòu)2集合類型3目錄5.1
關(guān)于雜湊5.1
關(guān)于雜湊雜湊(Hashing)是計(jì)算機(jī)科學(xué)中一種對(duì)數(shù)據(jù)的處理方法,通過某種特定的函數(shù)/算法(稱為雜湊函數(shù)/算法),將要檢索的項(xiàng)與用來檢索的索引(稱為雜湊,或者雜湊值)關(guān)聯(lián)起來,生成一種便于搜索的數(shù)據(jù)結(jié)構(gòu)(稱為雜湊表,散列)。它也常被用作一種信息安全的實(shí)施方法,由一串?dāng)?shù)據(jù)中經(jīng)過雜湊算法計(jì)算出來的數(shù)據(jù)指紋,經(jīng)常用來識(shí)別文檔與數(shù)據(jù)是否有被篡改。5.1
關(guān)于雜湊常見的雜湊演算法有MD5、SHA-1、SHA-256等等,可用來求得數(shù)據(jù)的數(shù)字指紋,其應(yīng)用相當(dāng)廣泛,例如網(wǎng)站若提供大型文件,可一并附上該文件的雜湊值,下載后便能以雜湊值檢查文件是否完整無缺。P2P(peer-to-peer)對(duì)等網(wǎng)絡(luò)文件分享,諸如BitTorrent、eMule、BitComet,也會(huì)使用雜湊技術(shù),借以檢驗(yàn)下載的文件片段是否正確。雜湊因具有不可逆的性質(zhì),無法從雜湊值逆向推算原先的數(shù)據(jù),所以也用于密碼加密,當(dāng)要存儲(chǔ)密碼時(shí),并非直接存儲(chǔ),而是存儲(chǔ)密碼的雜湊值,即便被偷了,也無法破解得知密碼。5.1
關(guān)于雜湊字典(dict)類型含有鍵值配對(duì),只要是可雜湊的對(duì)象(不可變對(duì)象都可雜湊)都能作為鍵,所以不像列表受限于從0起跳的連續(xù)整數(shù)索引值,字典可使用不連續(xù)的大數(shù)字作為鍵,例如學(xué)生的學(xué)號(hào),也可使用字符串作為鍵,例如汽車的車牌、日期時(shí)間、人物姓名、水果名等等;集合類型則是儲(chǔ)存某些東西的數(shù)據(jù)結(jié)構(gòu),同樣的,可雜湊的對(duì)象方能成為集合的元素。字典類型在其他程序語言里可能稱為關(guān)聯(lián)式陣列、雜湊表、映射等,概念相同但細(xì)節(jié)不同。字典的創(chuàng)建字典的鍵與值字典生成式全局與局部字典應(yīng)用實(shí)例5.2字典結(jié)構(gòu)5.2
字典結(jié)構(gòu)與列表(list)是存儲(chǔ)一個(gè)個(gè)的對(duì)象,并以索引值(從0起跳的整數(shù))存取不同,字典是存儲(chǔ)鍵值配對(duì),透過鍵來存取相對(duì)應(yīng)的值。建立字典時(shí)可使用大括號(hào)“{}”,里面放進(jìn)以逗號(hào)隔開的鍵值配對(duì),鍵與值則以冒號(hào)“:”隔開,存取時(shí)仍使用方括號(hào)“[]”,在方括號(hào)內(nèi)放入鍵,便可存取相關(guān)聯(lián)的值。>>>d={} #建立空字典對(duì)象>>>d={'name':'Amy','age':27} #以大括號(hào)語法建立dict對(duì)象>>>d #字典不具順序性{'age':27,'name':'Amy'}>>>d['name'] #以方括號(hào)存取,類似于list'Amy'>>>d['age']=29 #dict是可變對(duì)象,可指派新值>>>d['score']=77 #但若是首次指派不存在的鍵,>>>d #便會(huì)建立該鍵值配對(duì)的關(guān)系{'age':29,'name':'Amy','score':77}>>>d['ape'] #但若取用時(shí)字典無此鍵,會(huì)發(fā)生錯(cuò)誤Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>KeyError:'ape' #鍵錯(cuò)誤5.2
字典結(jié)構(gòu)5.2
字典結(jié)構(gòu)圖5-1示意了上述程序代碼里的字典對(duì)象d,看起來跟列表很像,但字典的鍵不限定于整數(shù)。
字典示意圖5.2.1字典的創(chuàng)建字典是一種映射形式的類型,從“鍵”映射到“值”,值可以是任何類型的對(duì)象,例如字符串、整數(shù)、列表或另一個(gè)字典,鍵則是不可變對(duì)象,例如字符串、整數(shù)、元組,最常使用的是字符串與整數(shù)。使用字符串的話,便能以容易記憶的字符串作為鍵,若鍵為整數(shù)的話,可使用任何范圍的整數(shù),不像表的索引值必須從0開始計(jì)數(shù)。>>>d={'str':[0,1,2],(30,41,52):{'x':0,'y':1}}>>>d[(30,41,52)] #此鍵是個(gè)tuple,{'x':0,'y':1} #其值是個(gè)dict>>>d={1504301:'Amy',1504305:'Bob'}>>>d[1504301] #以學(xué)號(hào)(很大的整數(shù))作為鍵'Amy'5.2.1字典的創(chuàng)建除了以大括號(hào)包起來的字面值形式,也能透過內(nèi)置函數(shù)dict(也是類型dict的構(gòu)造函數(shù))來建立字典對(duì)象,其參數(shù)的形式非常多,非常方便。>>>d=dict(name='Amy',age=40,job='writer’)#以關(guān)鍵字參數(shù)指定鍵值配對(duì)>>>d #你看到的順序,不一定會(huì)和此處相同{'age':40,'job':'writer','name':'Amy'}>>>keys=['name','age','job'] #含有鍵的列表對(duì)象>>>values=['Amy',40,'writer']#含有值的列表對(duì)象>>>d2=dict(zip(keys,values)) #透過內(nèi)置函數(shù)zip組合>>>d2 #雖內(nèi)容物與d相同,但順序不同{'job':'writer','age':40,'name':'Amy'}5.2.1字典的創(chuàng)建>>>d3=dict(d2,name='Amanda')#以d2為基礎(chǔ),并以關(guān)鍵字參數(shù)>>>d3#指定鍵值配對(duì){'job':'writer','age':40,'name':'Amanda'}>>>d4=dict(zip(range(100,100+3),('Amy','Bob','Cathy')))>>>d4{100:'Amy',101:'Bob',102:'Cathy'}5.2.1字典的創(chuàng)建5.2.1字典的創(chuàng)建字典建立后,接下來便是各種支持字典的運(yùn)算符與方法。>>>d={'age':29,'name':'Amy','score':77}>>>len(d) #長(zhǎng)度,含有幾個(gè)鍵值配對(duì)3>>>'age'ind #測(cè)試字典有無此鍵True>>>deld['name'] #刪除此鍵(以及相對(duì)應(yīng)的鍵值配對(duì)關(guān)系)>>>'name'indFalse>>>d['name'] #以[]形式取用,若無該鍵會(huì)發(fā)生錯(cuò)誤Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>KeyError:'name'>>>d.get('name')#以方法get取用,若無該鍵會(huì)返回None>>>d.get('name','Amy')#若無該鍵就返回指定的缺省值,'Amy'#注意,字典內(nèi)仍無該鍵>>>d['name']='Amy'#以[]形式指派鍵值配對(duì)>>>d.setdefault('job')#以方法setdefault指派,若無該鍵,>>>d #缺省會(huì)指派為None{'job':None,'age':29,'score':77,'name':'Amy'}5.2.1字典的創(chuàng)建>>>d.setdefault('city','London') #加入此鍵值配對(duì)>>>d.setdefault('city') #已有此鍵,返回相對(duì)應(yīng)的值'London'5.2.1字典的創(chuàng)建5.2.1字典的創(chuàng)建雖然字典是一種映射形式的類型,但提供了各種方法,能把鍵、值,甚至是鍵值配對(duì)以符合序列類型的對(duì)象返回,那么,我們就能用“迭代”方法逐一處理。d={'a':1,'b':2,'c':3} #類型dictforkeyind: #放在for/in循環(huán)里,會(huì)提供鍵的可迭代項(xiàng)
print(key)forkeyind.keys(): #方法keys(),提供鍵的可迭代項(xiàng)
print(key)forvalueind.values(): #方法values(),提供值的可迭代項(xiàng)
print(value)fork,vind.items(): #方法items(),提供鍵值配對(duì)的可迭代項(xiàng)
print(k,v)5.2.1字典的創(chuàng)建再強(qiáng)調(diào)一次,字典類型的鍵值配對(duì)并無順序,就算是同樣的程序代碼,如果放到不同版本的Python來執(zhí)行、放到另一臺(tái)電腦上執(zhí)行,其結(jié)果所顯示的順序不一定相同,甚至每次執(zhí)行的結(jié)果都不同;換句話說,字典只提供鍵映射到值這樣的關(guān)系而已,并不保證順序性。字典類型的操作列于表7-1。5.2.1字典的創(chuàng)建表5-1字典操作5.2.2字典的鍵與值只要符合抽象類型Hashable(可散列)的對(duì)象,就能作為字典的鍵,最常用的是類型str(字符串)與int(整數(shù));可變類型如list、set、dict,都無法作為鍵。注意到整數(shù)1與浮點(diǎn)數(shù)1.0的雜湊值相同,但因?yàn)轭愋?oat無法精確地表示大部分的浮點(diǎn)數(shù),并不適合拿來作為字典的鍵,實(shí)際中也很少有人使用。>>>fromdecimalimportDecimal>>>fromfractionsimportFraction>>>d={1:111,'a':2,Decimal('3.14'):'pi',Fraction(1,3):1.3}>>>d{'a':2,1:111,Decimal('3.14'):'pi',Fraction(1,3):1.3}>>>hash(1.0),hash(1)(1,1) #雜湊值相同,>>>d[1.0],d[1] #所以會(huì)得到相同的對(duì)應(yīng)值(111,111)5.2.2字典的鍵與值5.2.2字典的鍵與值若鍵是字符串,也能使用構(gòu)造函數(shù)dict來建立字典對(duì)象,但因?yàn)樾枰詤?shù)的形式傳入,所以該鍵(字符串)必須符合Python的識(shí)別字規(guī)則,例如字符串'123abc'就無法以此形式建立。>>>dict(foo=1,bar=2,abc123=3)#以關(guān)鍵字參數(shù)傳入鍵與值{'foo':1,'bar':2,'abc123':3}>>>dict(foo=1,bar=2,123abc=3)#123abc不符合識(shí)別字規(guī)則
File"<stdin>",line1dict(foo=1,bar=2,123abc=3)^SyntaxError:invalidsyntax>>>d={'foo':1,'bar':2,'123abc':3} #以這種形式就沒問題了{(lán)'foo':1,'bar':2,'123abc':3}>>>d2=dict(d,foo=555,abc=999) #以先前的字典d為基礎(chǔ),>>>d2#再以關(guān)鍵字參數(shù)新增或更新鍵值配對(duì){'foo':555,'abc':999,'bar':2,'123abc':3}>>>k=['foo','bar'];v=[101,102] #以zip合并兩個(gè)列表,>>>d3=dict(zip(k,v),abc=999) #便可作為鍵值配對(duì)的提供者>>>d3{'foo':101,'abc':999,'bar':102}5.2.2字典的鍵與值5.2.2字典的鍵與值另外也能以字典類型的方法fromkeys來建立列表,此方法不屬于某一個(gè)實(shí)體對(duì)象,所以稱為類型方法。其首個(gè)參數(shù)可以是序列對(duì)象(或可迭代項(xiàng)),提供鍵,后一個(gè)參數(shù)(選用性)則是缺省值,若不指定則會(huì)是None。>>>dict.fromkeys(['a','b','c']){'a':None,'b':None,'c':None}>>>dict.fromkeys(['a','b','c'],999){'a':999,'b':999,'c':999}>>>dict.fromkeys(range(5),0){0:0,1:0,2:0,3:0,4:0}5.2.3字典生成式用來建立字典對(duì)象的字典生成式與列表生成式非常類似,只是語法稍有不同,它使用大括號(hào)“{}”包起來,在for的左邊必須是“k:v”的形式,提供鍵值配對(duì);同樣地,也能加上if進(jìn)行過濾。{表達(dá)式:表達(dá)式for名稱in可迭代項(xiàng)}{表達(dá)式:表達(dá)式for名稱in可迭代項(xiàng)if表達(dá)式}>>>{k:k**2forkinrange(5)} #鍵從0到4,值是平方{0:0,1:1,2:4,3:9,4:16}>>>dict([(k,k**2)forkinrange(5)]) #使用列表生成式與構(gòu)造函數(shù)dict,{0:0,1:1,2:4,3:9,4:16} #達(dá)到同樣的效果>>>d={'Amy':90,'Joe':45,'Kevin':33}>>>{k:vfork,vind.items()ifv<60}#僅拿出成績(jī)低于60的{'Joe':45,'Kevin':33}>>>li=['a','b','c']>>>{a:ifori,ainenumerate(li,start=101)}{'a':101,'b':102,'c':103} #為每個(gè)元素賦予某列舉值>>>dict(enumerate(li,start=1)) #呃,不一樣...{1:'a',2:'b',3:'c'}>>>dict(zip(li,range(101,101+len(li))))#弄出相同的字典了{(lán)'a':101,'b':102,'c':103}5.2.3字典生成式5.2.3字典生成式雖然某些字典生成式能以列表生成式與構(gòu)造函數(shù)dict改寫,但后者必須先建立列表對(duì)象,然后再傳入構(gòu)造函數(shù)dict,效能較為緩慢,從語法來看也較不簡(jiǎn)潔。5.2.4全局與局部Python會(huì)把“名稱”放在命名空間里,也就是把名稱與對(duì)象的綁定關(guān)系存儲(chǔ)在字典里。【程序?qū)嵗?-1】全局與局部命名空間。#symbol_table.pya=1b=2c=3deffoo(x,y):a='aaa'b='bbb'print(locals())print(globals())print('*'*10)foo(80,91)5.2.4全局與局部5.2.4全局與局部名稱a、b、c、foo被放在全局命名空間里。若調(diào)用函數(shù)foo,會(huì)進(jìn)入函數(shù)局部范圍,名稱x、y、a、b會(huì)被放在局部的命名空間里。以Python內(nèi)置函數(shù)globals取得含有全局名稱(與對(duì)象綁定關(guān)系)的字典,也稱為全局符號(hào)表,以locals取得含有局部名稱的字典(局部符號(hào)表)。上述程序代碼執(zhí)行后,會(huì)輸出如下的信息:{'a':1,'c':3,'b':2,'__builtins__':<module'builtins'(built-in)>,'__file__':'symbol_table.py','__package__':None,'__cached__':None,'__name__':'__main__','foo':<functionfooat0x7fe2d8ec>,'__doc__':None}**********{'a':'aaa','y':91,'b':'bbb','x':80}5.2.4全局與局部在全局字典里,你可看到名稱a、b、c、foo以及一些其他名稱,例如__?le__指向文件名的字符串,__name__則是目前所在模塊名,而__builtins__則指向內(nèi)置模塊,也因?yàn)橛兴?,Python才知道要去哪尋找內(nèi)置的函數(shù)、常數(shù)、異常。在局部字典里,可看到x、y、a、b,因字典不具順序性,所以并不會(huì)按照參數(shù)的順序、賦值語句的先后順序排列名稱。5.2.5字典應(yīng)用實(shí)例若需要根據(jù)某對(duì)象的內(nèi)容拿出相對(duì)應(yīng)的數(shù)據(jù)或執(zhí)行不同的程序代碼,往往會(huì)使用if/elif/elif.../else來實(shí)作,但可能太過冗長(zhǎng);可以把東西先放進(jìn)字典,然后直接取用即可。x='apple'result=Noneifx=='apple': #以一連串的if/elif.../else來做判斷,
result=1elifx=='banana':result=2elifx=='grape': #該執(zhí)行哪部分的程序代碼
result=3else:result=-1####上述程序代碼可改寫為:####x='apple'd={'apple':1,'banana':2,'grape':3}result=d.get(x,-1)5.2.5字典應(yīng)用實(shí)例5.2.5字典應(yīng)用實(shí)例因?yàn)楹瘮?shù)也是對(duì)象,也可作為值放進(jìn)字典里,這樣一來便可根據(jù)鍵來執(zhí)行相對(duì)應(yīng)的程序碼,例如:deff0():pass #準(zhǔn)備一些函數(shù)deff1():passdeff2():pass #作為值放進(jìn)字典里d={'apple':f0,'banana':f1,'grape':f2}x='apple'ifxind: #若有該鍵,
d[x]() #便取出對(duì)應(yīng)的值(函數(shù)對(duì)象)并調(diào)用執(zhí)行若字典的值可雜湊,便可逆轉(zhuǎn)鍵值配對(duì)。不過若值重復(fù)的話,逆轉(zhuǎn)后將會(huì)只剩一個(gè)鍵值配對(duì)?!境绦?qū)嵗?-2】逆轉(zhuǎn)字典的鍵值配對(duì)。#dict_invert.py#學(xué)生姓名與成績(jī)d={'Amy':45,'Bob':50,'Cathy':62,'David':45,'Eason':63,'Fred':78,'George':72,'Helen':82,'Ivan':100,'Jason':98,'Kevin':0,'Laura':100}#逆轉(zhuǎn)鍵值配對(duì)d2={v:kfork,vind.items()}#逆轉(zhuǎn)后,鍵100、值可能會(huì)是'Laura'或'Ivan',只剩一個(gè)5.2.5字典應(yīng)用實(shí)例5.2.5字典應(yīng)用實(shí)例因?yàn)樽值洳痪唔樞蛐?,若想要按照某種排序方式輸出或操作字典的話,可運(yùn)用內(nèi)置函數(shù)sorted來排序??稍賯魅胍粋€(gè)名為key的參數(shù),由它來指定根據(jù)什么來排序?!境绦?qū)嵗?-3】排序字典。#dict_sort.py#鍵是學(xué)生姓名,值是一個(gè)含有三項(xiàng)成績(jī)的tuple對(duì)象,假設(shè)成績(jī)依序是數(shù)學(xué)、歷史、英文d={'Amy':(45,60,33),'Bob':(50,62,78),'Cathy':(62,98,87),'David':(45,22,12),'Eason':(63,55,71),'Fred':(78,79,32)}forkinsorted(d.keys()): #根據(jù)鍵(姓名)排序
print(k,d[k])5.2.5字典應(yīng)用實(shí)例deffoo(item):returnitem[1][2] #根據(jù)英文成績(jī)來排序foriteminsorted(d.items(),key=foo):print(item)defbar(item):returnsum(item[1]) #根據(jù)總分來排序foriteminsorted(d.items(),key=bar):print(item)5.2.5字典應(yīng)用實(shí)例5.2.5字典應(yīng)用實(shí)例字符串格式化,包括運(yùn)算符“%”與字符串方法format,都可以運(yùn)用字典。集合的創(chuàng)建集合的元素集合的數(shù)學(xué)運(yùn)算集成生成式5.3集合類型5.3
集合類型接下來,我們來看看類型set(集合)。集合是一種不具順序性的容器類型,同一個(gè)對(duì)象只能放進(jìn)去一次。建立集合時(shí),字面值語法是以大括號(hào)“{}”包住想要的一個(gè)個(gè)元素,或調(diào)用內(nèi)置函數(shù)set,傳入可迭代項(xiàng)(提供一個(gè)個(gè)元素)。元素可以是任何不可變對(duì)象,例如int、tuple、str。>>>x={1,2,3,4,5} #以大括號(hào)包住集合元素>>>x{1,2,3,4,5}>>>x2=set([1,'a',(3,4),5]) #內(nèi)置函數(shù)set,傳入含有元素的列表>>>x2{1,'a',(3,4),5}>>>x3=set(range(1,5+1)) #內(nèi)置函數(shù)set,傳入含有元素的可迭代項(xiàng)>>>x4={0,1,[2,3,4]} #list是可變對(duì)象,發(fā)生錯(cuò)誤Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:unhashabletype:'list'5.3
集合類型5.3
集合類型上述程序中,x2對(duì)象的示意如圖所示。與字典相同,集合內(nèi)的元素也不具有順序性,類型set僅代表某東西是否存在于該集合內(nèi)。
集合示意>>>x={};type(x) #{}會(huì)建立空字典,不是空集合<class'dict'>>>>x={1,2,3,4,5}>>>x[0] #集合不具順序性,不支持索引存取方式Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:'set'objectdoesnotsupportindexing>>>len(x) #長(zhǎng)度,集合內(nèi)元素的個(gè)數(shù)5>>>1inx #判斷某對(duì)象存不存在于集合內(nèi)True5.3
集合類型>>>x.add(6) #加入新元素>>>x.add(6) #加入已有的元素,無作用>>>x.remove(1) #移除某元素>>>x.remove(7) #若該元素不存在于集合內(nèi),發(fā)生錯(cuò)誤Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>KeyError:7>>>x.discard(7) #移除某元素,若不存在并不會(huì)發(fā)生錯(cuò)誤>>>x{2,3,4,5,6}5.3
集合類型>>>x&{5,6,999} #“&”運(yùn)算符,交集(intersection){5,6}>>>x|{5,6,999} #“|”運(yùn)算符,聯(lián)集(union){2,3,4,5,6,999}>>>x-{5,6,999} #“-”運(yùn)算符,差集(difference){2,3,4}>>>x^{5,6,999} #“^”運(yùn)算符,對(duì)稱差集(symmetricdifference){2,3,4,999}5.3
集合類型5.3
集合類型當(dāng)想檢查兩個(gè)列表是否含有相同的元素,但不在乎順序與是否重復(fù)時(shí),便可利用類型set,非常便利。>>>li0=[0,1,2];li1=[2,2,1,0,2,1]#不同的列表>>>set(li1) #傳入內(nèi)置函數(shù)set,得到不重復(fù)元素的集合{0,1,2}>>>set(li0)==set(li1) #以集合的眼光來看是相等的True5.3
集合類型集合類型是一種不具順序性的容器類型,其元素必須是可雜湊的對(duì)象,記錄某對(duì)象在不在集合里。因?yàn)椴痪唔樞蛐?,所以集合不支持索引與切片的存取方式。5.3.1集合的創(chuàng)建建立集合時(shí),可使用被圓括號(hào)“()”包住、以逗號(hào)“,”隔開元素的字面值形式,或是使用類型set的構(gòu)造函數(shù)。調(diào)用構(gòu)造函數(shù)set時(shí),參數(shù)是個(gè)可迭代項(xiàng),負(fù)責(zé)提供一個(gè)個(gè)的元素,元素必須可雜湊。>>>empty_dict={} #這是空字典>>>empty_set=set() #這才是空集合>>>{'a','b','c'} #含有三個(gè)元素的集合{'c','b','a'} #集合不具順序性>>>{(0,1,2),3,3.14} #元素可以是任何不可變對(duì)象{(0,1,2),3.14,3}>>>set('abc') #使用構(gòu)造函數(shù)set,傳入序列對(duì)象{'c','b','a'}>>>set([30,41,52]) #傳入列表{41,52,30}5.3.1集合的創(chuàng)建>>>set(range(5)) #傳入可迭代項(xiàng){0,1,2,3,4}>>>s0=set(range(5))>>>set(s0) #傳入另一個(gè)集合對(duì)象{0,1,2,3,4}>>>len(s0) #長(zhǎng)度5>>>1ins0 #判斷里面是否含有某元素True5.3.1集合的創(chuàng)建5.3.2集合的元素集合建立后,因?yàn)槭强勺儗?duì)象,可使用集合專屬的方法原地修改其元素。>>>s={0,1,2,3,4,5}>>>s.add(6) #加入int對(duì)象6>>>s.add(3) #加入已有的元素,無作用>>>s.remove(0) #移除0>>>s{1,2,3,4,5,6}>>>s.remove(999) #若想移除的元素不存在,引發(fā)異常Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>KeyError:9995.3.2集合的元素>>>s.discard(999) #使用discard的話,元素不存在不會(huì)引發(fā)異常>>>s.pop() #隨機(jī)移除某元素、返回該元素2>>>s{3,4,5,6}>>>s1=s.copy() #淺復(fù)制>>>s.clear() #清空集合>>>s.pop() #若集合為空,pop會(huì)引發(fā)異常Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>KeyError:'popfromanemptyset'5.3.2集合的元素5.3.3集合的數(shù)學(xué)運(yùn)算集合有嚴(yán)謹(jǐn)?shù)臄?shù)學(xué)定義,Python也以運(yùn)算符和方法支持集合的數(shù)學(xué)運(yùn)算,包括聯(lián)集、交集、差集、對(duì)稱差集以及子集合、超集合的判斷。>>>s0={1,2,3,4} #測(cè)試用集合>>>s1={3,4,5,6,7}>>>s2={1,2,3}>>>s3={91,92,93}>>>s0==s1,s0==s0 #判斷是否含有同樣的元素(False,True)>>>s2<=s0,s2.issubset(s0) #子集合(True,True)>>>s2<s0,s0<s0 #真子集合(True,False)5.3.3集合的數(shù)學(xué)運(yùn)算>>>s0>=s2,s0.issuperset(s2) #超集合(True,True)>>>s0>s2,s0>s0 #真超集合(True,False)>>>s0|s1 #聯(lián)集,產(chǎn)生新集合對(duì)象{1,2,3,4,5,6,7}>>>s0&s1 #交集,產(chǎn)生新集合對(duì)象{3,4}>>>s0-s1 #差集,產(chǎn)生新集合對(duì)象{1,2}5.3.3集合的數(shù)學(xué)運(yùn)算>>>s0^s1 #對(duì)稱差集,產(chǎn)生新集合對(duì)象{1,2,5,6,7}>>>s0&s3,s0.isdisjoint(s3) #無交集(set(),True)5.3.3集合的數(shù)學(xué)運(yùn)算5.3.3集合的數(shù)學(xué)運(yùn)算同一種集合運(yùn)算,例如聯(lián)集,有運(yùn)算符“|”與方法“union”可用,但運(yùn)算符只能接受集合對(duì)象,而方法則可接受可迭代項(xiàng),例如列表。>>>s0={1,2,3,4}>>>s0|[3,4,5,6] #運(yùn)算符只能接受集合對(duì)象Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:unsupportedoperandtype(s)for|:'set'and'list'>>>s0.union([3,4,5,6]) #方法可以接受可迭代項(xiàng){1,2,3,4,5,6}>>>set('abc')&'bcd'Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:unsupportedoperandtype(s)for&:'set'and'str'>>>set('abc').intersection('bcd'){'c','b'}5.3.3集合的數(shù)學(xué)運(yùn)算5.3.3集合的數(shù)學(xué)運(yùn)算使用增強(qiáng)型賦值語句“|=、&=、-=、^=”時(shí)須小心,這是原地修改的動(dòng)作,不會(huì)產(chǎn)生新集合對(duì)象,而是更新(修改)語句左邊的集合對(duì)象。>>>s0={1,2,3,4}>>>s0|={3,4,5,6} #只示范“|=”,其余都類似>>>s0{1,2,3,4,5,6}5.3.4集合生成式集合也有集合生成式可用,其語法和列表生成式、字典生成式類似,一般形式如下:{表達(dá)式for名稱in可迭代項(xiàng)}{表達(dá)式for名稱in可迭代項(xiàng)if表達(dá)式}>>>li=['a','bar','candy','o','car']>>>{len(x)forxinli}{1,3,5} #記錄曾出現(xiàn)過的字符串長(zhǎng)度>>>{xforxinliiflen(x)==1}{'a','o'} #只收錄長(zhǎng)度為1的字符串>>>li=[0,1,1,2,2,3,3,4,5,5,6]>>>{xforxinliifli.count(x)==2}{1,2,3,5} #挑出在原列表出現(xiàn)2次的元素5.4字典與集合的訪問接口可雜湊項(xiàng)映射5.4
字典與集合的訪問接口在學(xué)習(xí)了字典與集合的基本知識(shí)后,我們來介紹相關(guān)的抽象類型,了解字典與集合提供哪些存取接口。5.4.1可雜湊項(xiàng)之前介紹類型dict時(shí),我們說“鍵”可以是任何不可變對(duì)象,這種說法還不夠正確,應(yīng)該說任何“可雜湊項(xiàng)(hashable)”都可作為字典的鍵。Python有個(gè)抽象類型Hashable,符合此接口的對(duì)象可依照雜湊演算法算出獨(dú)一無二的雜湊值,只要對(duì)象不相同,就會(huì)得到不同的雜湊值。Python內(nèi)置的不可變類型都符合此抽象類型,而內(nèi)置的可變類型則都不符合。調(diào)用內(nèi)置函數(shù)hash可得到某對(duì)象的雜湊值,但實(shí)際中很少直接使用該值。>>>fromcollections.abcimport*>>>issubclass(int,Hashable) #內(nèi)置的不可變類型都符合Hashable接口True>>>issubclass(tuple,Hashable)True>>>issubclass(list,Hashable) #內(nèi)置的可變類型,不符合Hashable接口False #因?yàn)榭勺儗?duì)象的內(nèi)容會(huì)改變,其雜湊值不定>>>issubclass(dict,Hashable)False>>>hash(1),hash('abc'),hash((30,41,52))(1,-39521455,1696699620) #不可變對(duì)象擁有獨(dú)一無二的雜湊值5.4.1可雜湊項(xiàng)>>>a=1;b='abc';c=(30,41,52)>>>hash(a),hash(b),hash(c) #既然a==1為真,內(nèi)容相同,(1,-39521455,1696699620) #那么其雜湊值也會(huì)相同>>>hash([0,1,2]) #不可變對(duì)象沒有雜湊值Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:unhashabletype:'list'>>>hash('name'),hash('age'),hash('score')(1574142124,537780116,-23663026)>>>hash(1),hash('a'),hash((3,4)),hash(5)(1,738615097,1699342716,5)5.4.1可雜湊項(xiàng)5.4.1可雜湊項(xiàng)不可變對(duì)象在其生存周期內(nèi)內(nèi)容絕對(duì)不變,所以其雜湊值不僅獨(dú)一無二,而且也不會(huì)改變,可作為字典的存儲(chǔ)依據(jù);所以較正確的字典示意圖應(yīng)如圖所示,字典其實(shí)是存儲(chǔ)“對(duì)象的雜湊值”與“值(任何對(duì)象)”的配對(duì)關(guān)系。下次當(dāng)你給定某鍵時(shí),字典就會(huì)算出該鍵的雜湊值,然后取出相對(duì)應(yīng)的值。
字典示意圖5.4.1可雜湊項(xiàng)若對(duì)象屬于容器類型,那么不僅對(duì)象本身必須不可變,其內(nèi)容也必須不可變,方可算是不可變對(duì)象。所以,tuple對(duì)象本身雖不可變,但若含有可變對(duì)象(例如list),那么該對(duì)象就不算是不可變,無法作為字典的鍵。>>>li=[0,1,2] #list對(duì)象,可變>>>t=(3,4,li) #tuple對(duì)象,含有可變對(duì)象>>>d={'a':1,t:2} #無法作為字典的鍵Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:unhashabletype:'list'5.4.1可雜湊項(xiàng)同樣的道理,類型set也不是直接存儲(chǔ)某對(duì)象,而是存儲(chǔ)雜湊值。當(dāng)把某對(duì)象放進(jìn)集合時(shí),會(huì)先算出雜湊值再放進(jìn)去;當(dāng)要測(cè)試某對(duì)象存不存在集合內(nèi)時(shí),只要算出對(duì)象的雜湊值,然后再檢查即可(見圖示意)。
集合示意圖5.4.1可雜湊項(xiàng)因?yàn)殡s湊演算法的特性,給定某內(nèi)容(對(duì)象)就算出相對(duì)應(yīng)的雜湊值,若對(duì)象不同就必定會(huì)得到不一樣的雜湊值,如此一來便能輕松得到字典與集合的功能。還請(qǐng)注意,不同Python版本可能會(huì)使用不同的雜湊演算法,不同平臺(tái)的Python實(shí)現(xiàn)也可能使用不一樣的雜湊演算法,所以你執(zhí)行上述程序時(shí),不會(huì)得到跟實(shí)例一樣的雜湊值。5.4.2映射項(xiàng)圖7-5顯示了與以映射(Mapping)為中心的相關(guān)抽象類型,類型dict符合抽象類型MutableMapping(可變映射)定義的接口,而且dict也是目前Python唯一的內(nèi)置映射類型;類型set符合抽象類型Set定義的接口。
映射相關(guān)的抽象類型層級(jí)5.4.2映射項(xiàng)我們先從類型set的抽象類型Set著手,因?yàn)樗莻€(gè)容器類型,很自然地繼承了抽象類型Sized與Container,所以可使用內(nèi)置函數(shù)len算出長(zhǎng)度(含有元素個(gè)數(shù)),并以運(yùn)算符“in”檢查某對(duì)象是否存在于集合之中。而且也符合可迭代項(xiàng)接口,所以可使用內(nèi)置函數(shù)iter得到迭代器,然后調(diào)用next逐一取出其中的元素,只不過因?yàn)轭愋蛃et不具順序性,所以我們并不知道迭代器會(huì)以何順序給出元素。>>>x={2,'a',(3,5),'b',17} #類型set>>>len(x) #長(zhǎng)度,元素的個(gè)數(shù)5>>>'b'inx #成員關(guān)系運(yùn)算符True>>>xit=iter(x)#取得迭代器>>>next(xit),next(xit)#取出前兩個(gè)元素,(17,'a')#注意,不具順序性>>>[eforeinxiftype(e)isint]#既然符合Iterable接口[17,2] #所以可用于需要迭代協(xié)定的地方5.4.2映射項(xiàng)5.4.2映射項(xiàng)然后是類型dict符合的接口面,抽象類型Mapping(映射)與MutableMapping(可變映射),同樣的,因?yàn)閷儆谌萜黝愋?,所以也都繼承了Sized與Container,并擁有許多字典專屬的方法。>>>d={'name':'Amy','age':40,'score':77}>>>len(d) #長(zhǎng)度,鍵值配對(duì)的個(gè)數(shù)3>>>'age'ind #“in”運(yùn)算符,某鍵是否存在True>>>d['name'] #以鍵取出值'Amy'>>>d['job']='wrier' #重新指派,新增或更新>>>d.pop('name') #移除指定鍵(與其鍵值配對(duì))'Amy'5.4.2映射項(xiàng)>>>d.pop('abc') #若不存在該鍵,發(fā)生錯(cuò)誤Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>KeyError:'abc'>>>d.pop('abc','default')#指定不存在該鍵時(shí)應(yīng)返回的缺省值'default'
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 軟件開發(fā)測(cè)試維護(hù)協(xié)議
- 大數(shù)據(jù)應(yīng)用平臺(tái)開發(fā)合作協(xié)議
- 微機(jī)課程設(shè)計(jì)信號(hào)發(fā)生器
- 外貿(mào)銷售合同范本模板大全2025年
- 2025年食用菌菌種買賣合同
- 教育在線服務(wù)平臺(tái)開發(fā)合作協(xié)議
- 金融產(chǎn)品研發(fā)合作協(xié)議
- 托班身體感官課程設(shè)計(jì)
- 水平位移監(jiān)測(cè)課程設(shè)計(jì)
- 2025年個(gè)人傭金協(xié)議書
- 小學(xué)少先隊(duì)活動(dòng)課贛教三年級(jí)上冊(cè)主題一唱響嘹亮的隊(duì)歌勇敢前進(jìn)
- 拉丁字母字體造型規(guī)律課件
- 《穿井得一人》《桑中生李》閱讀練習(xí)及答案
- 五年級(jí)下冊(cè)第三單元百年追夢(mèng)復(fù)興中華《不甘屈辱奮勇抗?fàn)?虎門銷煙》教案
- 裝飾裝修工程重點(diǎn)、難點(diǎn)分析及解決方案
- 2022年《導(dǎo)游業(yè)務(wù)》期末試卷及答案
- 高考生物生態(tài)大題習(xí)題20題版含答案及解析
- 人員信息登記表
- 大學(xué)生自我效能感量表及計(jì)分方法
- T∕CAAA 053-2020 鴨飼養(yǎng)標(biāo)準(zhǔn)
- (3)110KV配電裝置安裝單位工程質(zhì)量驗(yàn)收評(píng)定表1
評(píng)論
0/150
提交評(píng)論