1.其中涉及__hash__與__eq__這兩個內置方法.算法
2.列如: 要求用類生成多個對象,其中姓名和性別相同的對象可認爲是同一我的,用set原理作去重app
class People:函數
def __init__(self,name,age,sex):spa
self.name=name對象
self.age=age內存
self.sex=sex字符串
def __hash__(self): 對象找自帶的hash算法,原set的算法是算所有,如今改成了算自定義的部分hash
res=hash(self.name+self.sex)it
return res 返回的hash值和原數據類型作綁定再加入集合中,如需取出則給出原數據類型class
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__的運算標準修改爲了對象中的姓名+性別的形式組成的字符串,因此運算時
只會運算這個字符串,因此成了姓名和性別相同的去重,而無論其他部分是否相同.