set去重應用
1.其中涉及__hash__與__eq__這兩個內置方法.
2.列如: 要求用類生成多個對象,其中姓名和性別相同的對象可認為是同一個人,用set原理做去重
class People:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def __hash__(self): 對象找自帶的hash算法,原set的算法是算全部,現在改為了算自定義的部分
res=hash(self.name+self.sex)
return res 返回的hash值和原數據類型做綁定再加入集合中,如需取出則給出原數據類型
def __eq__(self,other): 發現重復的hash值自動觸發,並把重復的這兩個拿出來做對比
if self.name+self.sex==other.name+other.sex: 原set對比的是全部,現在對比的是自定義的部分
return True 如返回True則拋棄,Flase則重新計算並加入.
people_lis=[]
for i in range(1,200):
people_lis.append(People(‘張三’, i ,’男’))
for i in range(1,200):
people_lis.append(People(‘李四’, i ,’女’))
for i in people_lis:
print(i.__dict__)
個人理解:首先,這個東西要先搞明白集合的運行原理,或者說去重原理吧. set(可叠代對象).
1.先說集合的原理吧.集合自帶有類似於for循環的機制,會把放入其中的可叠代對象中的元素依次拿出來用
自帶的__hash__做hsah(元素)的算法,然後在內存中把其保存為:元素名+指向的形式(
是存放hash值的格子),當循環到某個元素的時候發現其Hash出來的值對應的格子已經有東西了,這時
候會生成:(當前元素==已存在的hash值對應的元素名)這樣的一個形式來觸發自帶的__eq__方法,如果這
兩個比較後的值為True,則拋棄當前元素不予處理.如果為Flase,則再次進行一系列運算,從而保證得到一個
不同的值再予以保存.
2.再來說說這個列子中的變化. 首先給了set一個可叠代的列表,set會利用自帶的循環機制挨個拿出來列表
中的每個元素,然後用自帶的hash算法準備給元素進行運算,此時必然是hash(元素)這麽的一個形式,但是這
種形式在此列中還有另一層含義,那就是調用對象的hash函數的意思,對象本類此時就具有這個函數,於是
就走了對象自己的了,然而自己的hash算法是經過修改的,就是提取對象中某一部分來進行hsah運算,不做
對象整體的運算,運算完成後會在內存中保存成(完整對象名+修改算法後的指向).當下一次循環來的對象
提取相同部分做完運算,如發現該指向已然有東西了,set準備再次用==來對比當前對象和已存對象值是
否相同時( 此時形式為:當前對象==已存對象).這個形式的另一層意義就起作用了,這是要調set的__eq__
方法,對象本類就有該方法,於是走的就是本類的__eq__方法,但是本類的這個東西也是經過修改的,修改的
是對比對象中某一段的值是否相同,相同則拋棄不予處理,不同則存起來.
因自帶的__hash__ 和 __eq__的運算標準修改成了對象中的姓名+性別的形式組成的字符串,所以運算時
只會運算這個字符串,所以成了姓名和性別相同的去重,而不管其余部分是否相同.
set去重應用