set或dict字典去重本質原理
阿新 • • 發佈:2019-02-13
去重本質原理
- __hash__值不等時,肯定不能去重
- __hash__值相等時,稱hash衝突,衝突後得看__eq__是否相等,若相等則去重
例項hash工作原理
- 在__hash__返回必須為整數
- __hash__需自行定義hash的內容
任意例項hash為同一整數
- 說明hash返回值是由__hash__控制
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def __hash__(self):
return 5000000
a = Point(1 ,2)
b = Point(2,1)
print(hash(a))
print(hash(b))
執行結果:
5000000
5000000
不同例項hash值可能相等
- 說明hash演算法決定例項hash值是否相等
- 舉例:不同的座標點,hash演算法採用x+y的值,因此只要x+y相等,則hash值即相等
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def __hash__(self):
return self.x + self.y
a = Point(1,2)
b = Point(2 ,1)
print(hash(a))
print(hash(b))
執行結果:
3
3
正確hash演算法策略
- 要避免hash衝突,首先要儘可能的演算法要不一致
- 座標點通過構建元組(x,y),對元組進行hash,因此只要x和y任意一個不相等,則hash值就不等
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def __hash__(self):
return hash((self.x,self.y))
a = Point(1,2)
b = Point(2 ,1)
print(hash(a))
print(hash(b))
執行結果:
3713081631934410656
3713082714465905806
驗證集合__hash__不等去重與否
hash值不等時,肯定不能去重
在字典和集合,hash值相當於門牌號碼,都不在一個房間裡,肯定不能去重,去重的前提時,在一個房間裡,是否為同一個值,如果時同一個值時,才能去重,不是同一個值時,不能去重,因此又引入__eq__判斷是否相等的特殊屬性。
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def __hash__(self):
return hash((self.x,self.y))
def __repr__(self):
return "Point({},{})".format(self.x,self.y)
a = Point(1,2)
b = Point(2,1)
print(hash(a))
print(hash(b))
print({a,b})
執行結果:
3713081631934410656
3713082714465905806
{Point(1,2), Point(2,1)}
hash值相等時,能否去重
- hash值相同時,說明在同一個房間內了,能否去重要根據__eq__是否為同一個資料了
- 如下例項,hash值相等,但是沒有去重,因為不支援判斷是否相等即eq屬性
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def __hash__(self):
return self.x+self.y
def __repr__(self):
return "Point({},{})".format(self.x,self.y)
a = Point(1,2)
b = Point(2,1)
print(hash(a))
print(hash(b))
print({a,b})
執行結果:
3
3
{Point(2,1), Point(1,2)}
hash值相等,eq策略值不等不去重
- 當eq值不等時,說明同一個房間放著兩個不同資料,當然不能去重
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def __hash__(self):
return self.x+self.y
def __repr__(self):
return "Point({},{})".format(self.x,self.y)
def __eq__(self,other):
return self.x == other.y and self.y == other.y
a = Point(1,2)
b = Point(2,1)
print(hash(a))
print(hash(b))
print({a,b})
執行結果:
3
3
{Point(2,1), Point(1,2)}
hash值相等,eq策略值相等時,去重
- 當eq策略值相等時,說明就是同一個值了
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def __hash__(self):
return self.x+self.y
def __repr__(self):
return "Point({},{})".format(self.x,self.y)
def __eq__(self,other):
return self.x == other.y and self.y == other.x
a = Point(1,2)
b = Point(2,1)
print(hash(a))
print(hash(b))
print({a,b})
執行結果:
3
3
{Point(1,2)}
江湖案例
一山不容二虎,eq的策略是什麼?頭把交椅,若一個山上有兩個都想坐頭把交椅,則必須去重,只能留一個,相當於宋江火併王倫。若一個當頭領,一個當軍師,此時二者都可以留。因此要根據eq策略決定存留。