解讀Python中字典的key都可以是什么_第1頁
解讀Python中字典的key都可以是什么_第2頁
解讀Python中字典的key都可以是什么_第3頁
解讀Python中字典的key都可以是什么_第4頁
解讀Python中字典的key都可以是什么_第5頁
已閱讀5頁,還剩1頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

第解讀Python中字典的key都可以是什么目錄Python字典的key都可以是什么答解釋注意

Python字典的key都可以是什么

一個對象能不能作為字典的key,就取決于其有沒有__hash__方法。所以所有python自帶類型中,除了list、dict、set和內(nèi)部至少帶有上述三種類型之一的tuple之外,其余的對象都能當(dāng)key。

比如數(shù)值/字符串/完全不可變的元祖/函數(shù)(內(nèi)建或自定義)/類(內(nèi)建或自定義)/方法/包等等你能拿出手的,不過有的實際意義不高。還有數(shù)值型要注意,因為兩個不同的相等數(shù)字可以有相同的哈希值,比如1和1.0。

解釋

代碼版本:3.6.3;文檔版本:3.6.6

Unlikesequences,whichareindexedbyarangeofnumbers,dictionariesareindexedbykeys,whichcanbeanyimmutabletype;stringsandnumberscanalwaysbekeys.Tuplescanbeusedaskeysiftheycontainonlystrings,numbers,ortuples;ifatuplecontainsanymutableobjecteitherdirectlyorindirectly,itcannotbeusedasakey.Youcantuselistsaskeys,sincelistscanbemodifiedinplaceusingindexassignments,sliceassignments,ormethodslikeappend()andextend().

字典的鍵可以是任意不可變類型,需要注意的是tuple元組作為鍵時,其中不能以任何方式包含可變對象。

那。。到底什么樣的是不可變類型呢?不可能給對象專門標(biāo)注一個屬性是可變類型還是不可變類型啊,這沒有任何其他意義,一定是通過其他途徑實現(xiàn)的。把list當(dāng)做鍵試一下

a=[1,2,3]

d={a:a}

#第二行報錯:

#TypeError:unhashabletype:'list'

報錯說list類型是不可哈希的,噢,原來是靠能不能hash來判斷的,另外文檔下面接著說同一字典中每個鍵都是唯一的,正好每個對象的哈希值也是唯一的,對應(yīng)的很好。

Itisbesttothinkofadictionaryasanunorderedsetofkey:valuepairs,withtherequirementthatthekeysareunique(withinonedictionary).

查看源代碼可以看到object對象是定義了__hash__方法的,

而list、set和dict都把__hash__賦值為None了

#部分源碼

classobject:

"""Themostbasetype"""

def__hash__(self,*args,**kwargs):

#realsignatureunknown

"""Returnhash(self)."""

pass

classlist(object):

__hash__=None

classset(object):

__hash__=None

classdict(object):

__hash__=None

那這樣的話。。。我給他加一個hash不就能當(dāng)字典的key了,key不就是可變的了。

注意

此處只是我跟著想法隨便試,真的應(yīng)用場景不要用可變類型作為字典的key。

classMyList(list):

"""比普通的list多一個__hash__方法"""

def__hash__(self):

#不能返回hash(self)

#hash(self)會調(diào)用self的本方法,再調(diào)用回去,那就沒完了(RecursionError)

#用的時候要注意實例中至少有一個元素,不然0怎么取(IndexError)

returnhash(self[0])

l1=MyList([1,2])

#print(l1)-[1,2]

d={l1:'Can'}

print(d)

#--

{[1,2]:'Can'}

l1.append(3)

print(d)

#{[1,2,3]:'Can'}

print(d[l1])

#--

Can

到這里就可以肯定的說,一個對象能不能作為字典的key,就取決于其有沒有__hash__方法。所以所有python自帶類型中,目前我已知的除了list、dict、set和內(nèi)部帶有以上三種類型的tuple之外,其余的對象都能當(dāng)key。而我們自己定義的類,一般情況下都直接間接的和object有關(guān),都帶有__hash__方法。

另外我想到,既然字典的鍵是唯一的,而哈希值也是唯一的,這么巧,鍵的唯一性不會就是用哈希值來確定的吧?我上一個例子中__hash__方法返回的是0號元素的哈希值,那我直接用相同哈希值的對象是不是就能改變那本來不屬于它的字典值呢?

classMyList(list):

def__hash__(self):

returnhash(self[0])

l1=MyList([1,2])

#print(l1)-[1,2]

d={}

d[l1]=l1

print(d)

#{[1,2]:[1,2]}

d[1]=1

print(d)

#{[1,2]:[1,2],1:1}

竟然沒有改成功而是新添加了一個鍵值對,可self[0]就是1啊,哈希值一樣啊,怎么會不一樣呢?難道要鍵的值一樣才能判斷是同一個鍵嗎?重寫__eq__方法試一下。

classMyList(list):

def__hash__(self):

returnhash(self[0])

def__eq__(self,other):

returnself[0]==other

l1=MyList([1,2])

#print(l1)-[1,2]

d={}

d[l1]=l1

print(d)

#{[1,2]:[1,2]}

d[1]=1

print(d)

#{[1,2]:1}

這回成功了,那就是__hash__返回值相等,且eq判斷也相等,才會被認(rèn)為是同一個鍵。那這兩個先判斷哪個呢?加個代碼試一下

classMyList(list):

def__hash__(self):

print('hashisrun')

returnhash(self[0])

def__eq__(self,other):

print('eqisrun')

returnself[0]==other

l1=MyList([1,2])

#print(l1)-[1,2]

d={}

d[1]=1

d[l1]='l1'

print(d)

#結(jié)果:

#hashisrun

#eqisrun

#{1:'l1'}

__hash__先執(zhí)行,另外字典在內(nèi)存中存儲數(shù)據(jù)的位置和鍵的hash也是有關(guān)的,邏輯上也像印證。

先計算hash,找到相對應(yīng)的那片內(nèi)存空間,里面沒有值的話就直接寫入,對于字典來說就是新增鍵值對;如

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論