成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Python兩個(gè)對(duì)象相等的原理

rottengeek / 2456人閱讀

摘要:因此我們可以得出結(jié)論,如果兩個(gè)對(duì)象相等的話,那它們的值必然也是相等的。如果定義了一個(gè)可比較的對(duì)象,那么最好保證對(duì)象值相關(guān)的屬性在生命周期內(nèi)不能發(fā)生改變,不然會(huì)發(fā)生意想不到的錯(cuò)誤。

概述

??大部分的python程序員平時(shí)編程的時(shí)候,很少關(guān)心兩個(gè)對(duì)象為什么相等,因?yàn)榻坛毯徒?jīng)驗(yàn)來(lái)說(shuō),他們就應(yīng)該相等,比如1==1就應(yīng)該返回True,可是當(dāng)我們想要定義自己的對(duì)象或者修改默認(rèn)的對(duì)象行為時(shí),通常會(huì)因?yàn)椴涣私庠矶鴮?dǎo)致各種奇奇怪怪的錯(cuò)誤。

兩個(gè)對(duì)象如何相等

??兩個(gè)對(duì)象如何才能相等要比我們想象的復(fù)雜很多,但核心的方法是重寫__eq__方法,這個(gè)方法返回True,則表示兩個(gè)對(duì)象相等,否則,就不相等。相反的,如果兩個(gè)對(duì)象不相等,則重寫__ne__方法。
??默認(rèn)情況下,如果你沒有實(shí)現(xiàn)這個(gè)方法,則使用父類(object)的方法。父類的方法比較是的兩個(gè)對(duì)象的ID(可以通過(guò)id方法獲取對(duì)象ID),也就是說(shuō),如果對(duì)象的ID相等,則兩個(gè)對(duì)象也就相等。因此,我們可以得知,默認(rèn)情況下,對(duì)象只和自己相等。例如:

>>> class A(object):
...     pass
...
>>>
>>> a = A()
>>> b = A()
>>> a == a
True
>>> a == b
False
>>> id(a)
4343310992
>>> id(b)
4343310928

??Python2程序員經(jīng)常犯的一個(gè)錯(cuò)誤是,只重寫了__eq__方法,而沒有重寫__ne__方法,導(dǎo)致不可預(yù)計(jì)的錯(cuò)誤。而Python3會(huì)自動(dòng)重寫__ne__方法,如果你沒有重寫的話。

對(duì)象的Hash方法

??Python里可Hash的對(duì)象,都有一個(gè)數(shù)字ID代表了它在python里的值,這個(gè)ID是由對(duì)象的__hash__方法返回的。因此,如果想讓一個(gè)對(duì)象可Hash,那必須實(shí)現(xiàn)__hash__方法和之前提到的__eq__方法。和對(duì)象相等一樣,默認(rèn)情況下,對(duì)象的__hash__方法繼承自O(shè)bject對(duì)象,而Object對(duì)象的__hash__方法只計(jì)算對(duì)象ID,因此兩個(gè)對(duì)象始終擁有兩個(gè)不一樣的hash id,不管他們是多么相似。
??當(dāng)我們把一個(gè)不可Hash的對(duì)象加入到set或者dict時(shí),會(huì)發(fā)生什么了?

>>> set().add({})
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unhashable type: "dict"
unhashable type: "dict"

原因是set()和dict()使用對(duì)象的hash值作為內(nèi)部索引,以便能快速索引到指定對(duì)象。因此,同一個(gè)對(duì)象返回相同的hash id就很重要了。

對(duì)象的Hash值在它的生命周期內(nèi)不能改變

??如果你想定義一個(gè)比較完美的對(duì)象,并且實(shí)現(xiàn)了__eq__和__hash__方法來(lái)定義對(duì)象的比較行為和hash值,那么你就需要保證對(duì)象的相關(guān)屬性不能發(fā)生更改。不然會(huì)導(dǎo)致很詭異的錯(cuò)誤,比如下面的例子。

>>> class C:
...     def __init__(self, x):
...         self.x = x
...     def __repr__(self):
...         return "C({"+str(self.x)+"})"
...     def __hash__(self):
...         return hash(self.x)
...     def __eq__(self, other):
...         return (
...             self.__class__ == other.__class__ and
...             self.x == other.x
...         )
>>> d = dict()
>>> s = set()
>>> c = C(1)
>>> d[c] = 42
>>> s.add(c)
>>> d, s
({C(1): 42}, {C(1)})
>>> c in s and c in d  # c is in both!
True
>>> c.x = 2
>>> c in s or c in d   # c is in neither!?
False
>>> d, s
({C(2): 42}, {C(2)})   # but...it"s right there!

在我們沒有修改對(duì)象的屬性時(shí)(c.x=2)之前,所有行為都符合預(yù)期。當(dāng)我們通過(guò)c.x=2時(shí)修改屬性后,執(zhí)行c in s or c in d返回False,但是內(nèi)容卻是修改后的,是不是很奇怪。這也就解釋了為什么str、tuple是可Hash的,而list和dict是不可hash的。

因此我們可以得出結(jié)論,如果兩個(gè)對(duì)象相等的話,那它們的hash值必然也是相等的。

總結(jié)

講了這么多有什么用了。

當(dāng)我們遇到unhashable type這個(gè)異常時(shí),我們能夠知道為什么報(bào)這個(gè)錯(cuò)誤。

如果定義了一個(gè)可比較的對(duì)象,那么最好保證對(duì)象hash值相關(guān)的屬性在生命周期內(nèi)不能發(fā)生改變,不然會(huì)發(fā)生意想不到的錯(cuò)誤。

轉(zhuǎn)載自我的博客捕蛇者說(shuō)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/41048.html

相關(guān)文章

  • Python無(wú)縫集成----基本特殊方法.(Mastering Objecting-orient

    摘要:第二章與的無(wú)縫集成基本特殊方法筆記中有有一些特殊的方法它們?cè)试S我們的類和更好的集成和方法通常方法表示的對(duì)象對(duì)用戶更加友好這個(gè)方法是有對(duì)象的方法實(shí)現(xiàn)的什么時(shí)候重寫跟非集合對(duì)象一個(gè)不包括其他集合對(duì)象的簡(jiǎn)單對(duì)象這類對(duì)象格式通常不會(huì)特別復(fù) 第二章 與Python的無(wú)縫集成----基本特殊方法.(Mastering Objecting-oriented Python 筆記) python中有有一...

    iamyoung001 評(píng)論0 收藏0
  • [譯] 與 Python 無(wú)縫集成——基本特殊方法 2

    摘要:有三個(gè)用例通過(guò)和方法定義相等性檢測(cè)和值不可變對(duì)象對(duì)于有些無(wú)狀態(tài)對(duì)象,例如這些不能被更新的類型。請(qǐng)注意,我們將為不可變對(duì)象定義以上兩個(gè)。 注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python __hash__() 方法 內(nèi)置hash()函數(shù)會(huì)調(diào)用給定對(duì)象的__hash__()方法。這里hash就是將(可能是復(fù)雜的)值縮減...

    hzc 評(píng)論0 收藏0
  • python學(xué)習(xí)筆記 序列

    內(nèi)置序列 容器序列 list, tuple, collections.deque等這些序列能存放不同類型的數(shù)據(jù) 扁平序列 str, byte, bytearray, memoryview, array.array, 這些序列只能容納一種類型數(shù)據(jù) 以上,容器序列存放的是他們所含任意類型對(duì)象的引用,而扁平序列存放的是值而不是引用 列表(list)是最基礎(chǔ)也是最重要的序列類型 列表推導(dǎo) >>> symb...

    godiscoder 評(píng)論0 收藏0
  • Python is 和 == 弄懂了嗎?

    摘要:中對(duì)象包含的三個(gè)基本要素,分別是身份標(biāo)識(shí)數(shù)據(jù)類型值對(duì)象之間比較是否相等可以用,也可以用。和都是對(duì)對(duì)象進(jìn)行比較判斷作用的,但對(duì)對(duì)象比較判斷的內(nèi)容并不相同。是標(biāo)準(zhǔn)操作符中的比較操作符,用來(lái)比較判斷兩個(gè)對(duì)象的值是否相等。 showImg(https://segmentfault.com/img/remote/1460000018591895?w=601&h=203); 在Python中一切都...

    zhongmeizhi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<