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

Python中使用__hash__和__eq__方法的問題

 更新時(shí)間:2022年09月27日 16:44:26   作者:Inotime  
這篇文章主要介紹了Python中使用__hash__和__eq__方法的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Python使用__hash__和__eq__的問題

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

 object.__hash__(self)

Called by built-in function hash() and for operations on members of hashed collections including set, frozenset, and dict.

 __hash__()方法會被上述四種情況調(diào)用。

If a class does not define an __eq__() method it should not define a __hash__()operation either; if it defines __eq__() but not __hash__(), its instances will not be usable as items in hashable collections. If a class defines mutable objects and implements an __eq__() method, it should not implement __hash__(), since the implementation of hashable collections requires that a key’s hash value is immutable (if the object’s hash value changes, it will be in the wrong hash bucket).

如果自定義類沒定義__eq__()方法,那也不應(yīng)該定義__hash__()方法。 

如果定義了__eq__()方法沒有定義__hash__()方法,那么它無法作為哈希集合的元素使用(這個(gè)hashable collections值得是set、frozenset和dict)。

這其實(shí)是因?yàn)橹貙慱_eq__()方法后會默認(rèn)把__hash__賦為None(文檔后面有說),像list一樣。 

class A:
? ? def __eq__(self, other):
? ? ? ? pass
?
?
a = A()
?
print(a.__hash__) ?# None
hash(a)
?
?
# TypeError: unhashable type: 'A'

還專門說明:如果定義可變對象的類實(shí)現(xiàn)了__eq__()方法,就不要再實(shí)現(xiàn)__hash__()方法,否則這個(gè)對象的hash值發(fā)生變化會導(dǎo)致被放在錯(cuò)誤的哈希桶中。這個(gè)可以用字典試一下,你的鍵值不在是一一對應(yīng)的,只要能讓這兩個(gè)方法返回一致的對象都能改動那個(gè)本不屬于自己的值,這篇文章的第五個(gè)例子就是這種情況。

User-defined classes have __eq__() and __hash__() methods by default; with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y). 

用戶定義的類默認(rèn)都有__eq__()和__hash__()方法,這是從object繼承的,如果你不重寫任何一個(gè),那么對這個(gè)類的兩個(gè)實(shí)例x,y來說,x is y ,x == y , hash(x) == hash(y)會同時(shí)成立/不成立,即只有在x就是y的時(shí)候成立。

A class that overrides __eq__() and does not define __hash__() will have its __hash__()implicitly set to None. When the __hash__() method of a class is None, instances of the class will raise an appropriate TypeError when a program attempts to retrieve their hash value, and will also be correctly identified as unhashable when checking isinstance(obj, collections.abc.Hashable).

 重寫了__eq__()方法的類會隱式的把__hash__賦為None。當(dāng)獲取實(shí)例的哈希值即用到了__hash__()方法時(shí)(只有上文提到的四種情況會用到這個(gè)方法)就會拋出TypeError錯(cuò)誤,上文例子演示過了。

并且isinstance判斷類型也能正確判斷。

# 直接安裝不成功 ?pip install collections2 才行
# collections2==0.3.0 ?A set of improved data types inspired by the standard library's collections module.
import collections
?
?
class A:
? ? def __eq__(self, other):
? ? ? ? pass
?
?
class B:
? ? pass
?
?
a = A()
b = B()
?
print(isinstance(a, collections.abc.Hashable)) ?# False
print(isinstance(b, collections.abc.Hashable)) ?# True

If a class that overrides __eq__() needs to retain the implementation of __hash__() from a parent class, the interpreter must be told this explicitly by setting __hash__ =<ParentClass>.__hash__.

If a class that does not override __eq__() wishes to suppress hash support, it should include __hash__ = None in the class definition. A class which defines its own __hash__() that explicitly raises a TypeError would be incorrectly identified as hashable by an isinstance(obj, collections.abc.Hashable) call.

 如果一個(gè)類重寫了__eq__()方法還需要能使用父類的__hash__()方法(上文已說默認(rèn)情況下是被賦值為None了),那就需要明確的說明一下:例class A;如果一個(gè)類沒有重寫__eq__()方法而又需要讓__hash__()失效,那就要明確的賦值為None,像list、set等的源碼那樣。

如果你重寫了一個(gè)會拋出異常的__hash__()方法,雖然使用時(shí)會拋出異常,但是類型判斷還是會判斷為是可哈希的,這是要注意的:例class B。

import collections
?
?
class A:
? ? def __eq__(self, other):
? ? ? ? pass
? ? __hash__ = object.__hash__
?
?
class B:
? ? def __hash__(self):
? ? ? ? raise TypeError('There is an error!')
?
?
a = A()
b = B()
?
print(isinstance(a, collections.abc.Hashable))
print(isinstance(b, collections.abc.Hashable))
hash(b)
?
?
# 結(jié)果:
# True
# True
# ...line 12, in __hash__...
# TypeError: There is an error!

文檔位置:3.6.6 object.__hash__

Python類中特殊方法__eq__和__hash__關(guān)系

class Point(object):

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return repr((self.id, self.x, self.y))

    def __eq__(self, other):
        return self.x == other.y and self.y == self.y

    def __hash__(self):
        return hash((self.x, self.y))

上面定義了一個(gè)二維點(diǎn)的類其中__repr__主要用來以一個(gè)字符串表示該類的實(shí)例,例如Point(1,2),在調(diào)試時(shí)打印該點(diǎn)會獲得字符串(1,2)。

當(dāng)對兩個(gè)點(diǎn)的實(shí)例進(jìn)行值的比較時(shí),比如p1=Point(1,1) p2=Point(1,2),判斷p1==p2時(shí)__eq__()會被調(diào)用,用以判斷兩個(gè)實(shí)例是否相等。在上述代碼中定義了只要x和y的坐標(biāo)相同,兩個(gè)點(diǎn)相等。需要注意,__eq__()對is不生效,==是比較的值,而is比較的是引用,也就是內(nèi)存地址。舉個(gè)例子,p1=Point(1,1) p2=Point(1,1),p1==p2為True,p1 is p2為False,只有p1 is p1為True。

在Python中對象分為可哈希對象和不可哈希對象,可哈希對象如字符串、數(shù)字、自定義的類、frozenset、元組,被稱作不可變對象,不可哈希對象如字典、列表、集合,被稱作可變對象。這里的不可變不是對象的值不可變,而是指對象創(chuàng)建后其hash值在其生命周期內(nèi)不會改變。用函數(shù)hash()取可哈希對象的hash值,只要是同一對象其hash值不會改變;而對不可哈希對象取hash值,例如對列表取hash值,會報(bào)錯(cuò),返回TypeError: unhashable type: 'list'??晒ο笠蚱鋒ash值不變可以用作字典的key,而不可哈希對象則不行。

當(dāng)需要對類的一個(gè)實(shí)例取其hash值時(shí),會調(diào)用__hash__()。一般來說,會把實(shí)例的所有屬性打包成元組,返回其hash值,從而實(shí)現(xiàn)自定義__hash__()。在用set()去重時(shí)就是對比hash值是否一樣,如果兩個(gè)對象hash值一樣代表重復(fù)。

用戶定義的類默認(rèn)帶有__eq__()和 __hash__()方法;使用它們與任何對象(自己除外)比較必定不相等,并且 x.__hash__()會返回一個(gè)恰當(dāng)?shù)闹狄源_保 x == y 同時(shí)意味著 x is y且 hash(x) == hash(y)。

如果一個(gè)類沒有定義__eq__()方法,那么也不應(yīng)該定義 __hash__()操作;如果它定義了__eq__()但沒有定義 __hash__(),那么__hash__()會被隱式地設(shè)為None,這個(gè)類就變成了不可哈希對象。如果一個(gè)類定義了可變對象并實(shí)現(xiàn)了 __eq__()方法,則不應(yīng)該實(shí)現(xiàn)__hash__(),因?yàn)榭晒<膶?shí)現(xiàn)要求鍵的哈希集是不可變的。例如,Point類中添加一個(gè)屬性li是一個(gè)列表,由于列表不可哈希所以強(qiáng)行放入包含屬性的元組中并返回其哈希值會報(bào)錯(cuò)。



如果使用默認(rèn)的__hash__()則不論如何改變一個(gè)實(shí)例的值其hash值都不變;反之,使用本文這種自定義的__hash__()方法,實(shí)例的值改變后,hash值就會改變。因此,自定義__hash__()方法的類的實(shí)例不應(yīng)該作為字典的key(強(qiáng)行作為key不會報(bào)錯(cuò),但是改變實(shí)例的屬性值會導(dǎo)致找不到key對應(yīng)的value),key的哈希值必須唯一不可變,key的hash值改變會導(dǎo)致找不到key對應(yīng)的value。






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

相關(guān)文章

  • Python 調(diào)用PIL庫失敗的解決方法

    Python 調(diào)用PIL庫失敗的解決方法

    今天小編就為大家分享一篇Python 調(diào)用PIL庫失敗的解決方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • PyTorch的深度學(xué)習(xí)入門教程之構(gòu)建神經(jīng)網(wǎng)絡(luò)

    PyTorch的深度學(xué)習(xí)入門教程之構(gòu)建神經(jīng)網(wǎng)絡(luò)

    這篇文章主要介紹了PyTorch的深度學(xué)習(xí)入門教程之構(gòu)建神經(jīng)網(wǎng)絡(luò),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • python Matplotlib畫圖之調(diào)整字體大小的示例

    python Matplotlib畫圖之調(diào)整字體大小的示例

    本篇文章主要介紹了python Matplotlib畫圖之調(diào)整字體大小的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11
  • python 音頻和視頻合并自動裁剪

    python 音頻和視頻合并自動裁剪

    本文主要介紹了python 音頻和視頻合并自動裁剪,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • 在Django中創(chuàng)建動態(tài)視圖的教程

    在Django中創(chuàng)建動態(tài)視圖的教程

    這篇文章主要介紹了在Django中創(chuàng)建動態(tài)視圖的教程,Django是Python重多人氣框架中最為著名的一個(gè),需要的朋友可以參考下
    2015-07-07
  • 對Python中DataFrame選擇某列值為XX的行實(shí)例詳解

    對Python中DataFrame選擇某列值為XX的行實(shí)例詳解

    今天小編就為大家分享一篇對Python中DataFrame選擇某列值為XX的行實(shí)例詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • python?針對在子文件夾中的md文檔實(shí)現(xiàn)批量md轉(zhuǎn)word

    python?針對在子文件夾中的md文檔實(shí)現(xiàn)批量md轉(zhuǎn)word

    這篇文章主要介紹了python?針對在子文件夾中的md文檔實(shí)現(xiàn)批量md轉(zhuǎn)word,但是自己保存的md文檔在不同的文件夾,而大部分只能實(shí)現(xiàn)同一文件夾內(nèi)的轉(zhuǎn)換,得出下列總結(jié),需要的朋友可以參考一下
    2022-04-04
  • 深入淺析Python中的yield關(guān)鍵字

    深入淺析Python中的yield關(guān)鍵字

    python中有一個(gè)非常有用的語法叫做生成器,所利用到的關(guān)鍵字就是yield。接下來腳本之家小編給大家?guī)砹薖ython中的yield關(guān)鍵字詳細(xì)解析,感興趣的朋友參考下吧
    2018-01-01
  • Python如何在類中定義裝飾器

    Python如何在類中定義裝飾器

    這篇文章主要介紹了Python如何在類中定義裝飾器的問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • 使用pytorch提取卷積神經(jīng)網(wǎng)絡(luò)的特征圖可視化

    使用pytorch提取卷積神經(jīng)網(wǎng)絡(luò)的特征圖可視化

    這篇文章主要給大家介紹了關(guān)于使用pytorch提取卷積神經(jīng)網(wǎng)絡(luò)的特征圖可視化的相關(guān)資料,文中給出了詳細(xì)的思路以及示例代碼,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-03-03

最新評論

晋宁县| 团风县| 通榆县| 高州市| 霞浦县| 平定县| 东乌珠穆沁旗| 湟源县| 绥化市| 盈江县| 扶余县| 乾安县| 巴林左旗| 集贤县| 万年县| 峨眉山市| 犍为县| 新野县| 咸阳市| 乐东| 大同县| 黔东| 杭锦旗| 囊谦县| 金塔县| 蓬安县| 文安县| 安义县| 虹口区| 石柱| 清流县| 贡觉县| 海兴县| 枣庄市| 治县。| 绍兴县| 永和县| 襄樊市| 宁武县| 惠安县| 福安市|