最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解讀Python中字典的key都可以是什么

 更新時(shí)間:2022年09月27日 16:40:52   作者:Inotime  
這篇文章主要介紹了解讀Python中字典的key都可以是什么,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Python字典的key都可以是什么

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

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

解釋

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

Unlike sequences, which are indexed by a range of numbers, dictionaries are indexed by keys, which can be any immutable type; strings and numbers can always be keys. Tuples can be used as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable object either directly or indirectly, it cannot be used as a key. You can’t use lists as keys, since lists can be modified in place using index assignments, slice assignments, or methods like append()and extend().

 字典的鍵可以是任意不可變類(lèi)型,需要注意的是tuple元組作為鍵時(shí),其中不能以任何方式包含可變對(duì)象。

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

a = [1, 2, 3]
d = {a: a}
?
?
# 第二行報(bào)錯(cuò):
# TypeError: unhashable type: 'list'

報(bào)錯(cuò)說(shuō)list類(lèi)型是不可哈希的,噢,原來(lái)是靠能不能hash來(lái)判斷的,另外文檔下面接著說(shuō)同一字典中每個(gè)鍵都是唯一的,正好每個(gè)對(duì)象的哈希值也是唯一的,對(duì)應(yīng)的很好。

It is best to think of a dictionary as an unordered set of key: value pairs, with the requirement that the keys are unique (within one dictionary).

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

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

# 部分源碼
?
class object:
? ? """ The most base type """
?
? ? def __hash__(self, *args, **kwargs): ?# real signature unknown
? ? ? ? """ Return hash(self). """
? ? ? ? pass
?
?
class list(object):
? ? __hash__ = None
?
?
class set(object):
? ? __hash__ = None
?
?
class dict(object):
? ? __hash__ = None

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

注意

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

class MyList(list):
? ? """比普通的list多一個(gè)__hash__方法"""
?
? ? def __hash__(self):
? ? ? ? # 不能返回hash(self)
? ? ? ? # hash(self)會(huì)調(diào)用self的本方法,再調(diào)用回去,那就沒(méi)完了(RecursionError)
? ? ? ? # 用的時(shí)候要注意實(shí)例中至少有一個(gè)元素,不然0怎么取(IndexError)
? ? ? ? return hash(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?

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

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

class MyList(list):
? ? def __hash__(self):
? ? ? ? return hash(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}

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

class MyList(list):
? ? def __hash__(self):
? ? ? ? return hash(self[0])
?
? ? def __eq__(self, other):
? ? ? ? return self[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判斷也相等,才會(huì)被認(rèn)為是同一個(gè)鍵。那這兩個(gè)先判斷哪個(gè)呢?加個(gè)代碼試一下

class MyList(list):
? ? def __hash__(self):
? ? ? ? print('hash is run')
? ? ? ? return hash(self[0])
?
? ? def __eq__(self, other):
? ? ? ? print('eq is run')
? ? ? ? return self[0] == other
?
?
l1 = MyList([1, 2]) ?# print(l1) -> [1, 2]
d = {}
d[1] = 1
d[l1] = 'l1'
print(d)
?
?
# 結(jié)果:
# hash is run
# eq is run
# {1: 'l1'}

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

先計(jì)算hash,找到相對(duì)應(yīng)的那片內(nèi)存空間,里面沒(méi)有值的話就直接寫(xiě)入,對(duì)于字典來(lái)說(shuō)就是新增鍵值對(duì);如果里面已經(jīng)有值了,那就判斷新來(lái)的鍵和原來(lái)的那里的鍵是不是相等,相等就認(rèn)為是一個(gè)鍵,對(duì)于字典來(lái)說(shuō)就是更新值,不相等就再開(kāi)空間,相當(dāng)于字典新增鍵值對(duì)。

在你驗(yàn)證自己想法的時(shí)候可能遇到__hash__和__eq__的一些想不到的麻煩,可以看這里:__hash__和__eq__的繼承使用問(wèn)題

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • python利用cv2庫(kù)讀取和保存視頻的操作步驟

    python利用cv2庫(kù)讀取和保存視頻的操作步驟

    這篇文章主要介紹了python利用cv2庫(kù)讀取和保存視頻的操作步驟,文中通過(guò)代碼示例給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-04-04
  • 通過(guò)實(shí)例解析Python return運(yùn)行原理

    通過(guò)實(shí)例解析Python return運(yùn)行原理

    這篇文章主要介紹了通過(guò)實(shí)例解析Python return運(yùn)行原理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • django正續(xù)或者倒序查庫(kù)實(shí)例

    django正續(xù)或者倒序查庫(kù)實(shí)例

    這篇文章主要介紹了django正續(xù)或者倒序查庫(kù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-05-05
  • 解決pytorch GPU 計(jì)算過(guò)程中出現(xiàn)內(nèi)存耗盡的問(wèn)題

    解決pytorch GPU 計(jì)算過(guò)程中出現(xiàn)內(nèi)存耗盡的問(wèn)題

    今天小編就為大家分享一篇解決pytorch GPU 計(jì)算過(guò)程中出現(xiàn)內(nèi)存耗盡的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-08-08
  • 詳解Python中 sys.argv[]的用法簡(jiǎn)明解釋

    詳解Python中 sys.argv[]的用法簡(jiǎn)明解釋

    本篇文章主要介紹了詳解Python中 sys.argv[]的用法簡(jiǎn)明解釋?zhuān)【幱X(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • python多進(jìn)程中的生產(chǎn)者和消費(fèi)者模型詳解

    python多進(jìn)程中的生產(chǎn)者和消費(fèi)者模型詳解

    這篇文章主要介紹了python多進(jìn)程中的生產(chǎn)者和消費(fèi)者模型,生產(chǎn)者是指生產(chǎn)數(shù)據(jù)的任務(wù),消費(fèi)者是指消費(fèi)數(shù)據(jù)的任務(wù)。當(dāng)生產(chǎn)者的生產(chǎn)能力遠(yuǎn)大于消費(fèi)者的消費(fèi)能力,生產(chǎn)者就需要等消費(fèi)者消費(fèi)完才能繼續(xù)生產(chǎn)新的數(shù)據(jù)
    2023-03-03
  • pandas將DataFrame的列變成行索引的方法

    pandas將DataFrame的列變成行索引的方法

    下面小編就為大家分享一篇pandas將DataFrame的列變成行索引的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • keras slice layer 層實(shí)現(xiàn)方式

    keras slice layer 層實(shí)現(xiàn)方式

    這篇文章主要介紹了keras slice layer 層實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-06-06
  • 在python中實(shí)現(xiàn)將一張圖片剪切成四份的方法

    在python中實(shí)現(xiàn)將一張圖片剪切成四份的方法

    今天小編就為大家分享一篇在python中實(shí)現(xiàn)將一張圖片剪切成四份的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • python3解析庫(kù)BeautifulSoup4的安裝配置與基本用法

    python3解析庫(kù)BeautifulSoup4的安裝配置與基本用法

    簡(jiǎn)單來(lái)說(shuō),BeautifulSoup就是Python的一個(gè)HTML或XML的解析庫(kù),我們可以用它來(lái)方便地從網(wǎng)頁(yè)中提取數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于python3解析庫(kù)BeautifulSoup4的安裝配置與基本用法的相關(guān)資料,需要的朋友可以參考下
    2018-06-06

最新評(píng)論

东阳市| 崇明县| 寿光市| 稷山县| 水城县| 茶陵县| 乌鲁木齐县| 论坛| 安图县| 清原| 舞阳县| 都匀市| 赣州市| 甘泉县| 芦溪县| 和政县| 定西市| 九江县| 石楼县| 台江县| 宁城县| 旬邑县| 怀仁县| 山阴县| 香港| 惠安县| 汨罗市| 南部县| 曲水县| 乐至县| 仲巴县| 奉贤区| 普兰县| 东宁县| 集安市| 海原县| 延吉市| 汕头市| 青田县| 阳泉市| 惠水县|