python的set去重原理_Set去重原理

在上篇文章《哈希值和可变性Hash value and mutability》最后说到set去重问题,所以这篇主要是通过实践来研究一下set去重背后的故事,当然也是参考了网上一些资料得到了一些启发,感谢那些陌生的喜欢分享的博友们。

set的简单应用

利用set中元素的唯一性,我们可以对list去重

list1 = [1,2,3,1,2,3]

print(set(list1))

# output: {1, 2, 3}

set去重的原理

set中元素的hash值不一样

class Person:

def __init__(self, name, identityId):

self.name = name

self.identityId = identityId

def __hash__(self):

print("%s call hash method"%self.name)

return hash(id(self))

def __eq__(self, other):

print("%s call eq method"%self.name)

if self.__dict__ == other.__dict__:

return True

else:

return False

p1 = Person('p1', 123456789)

p2 = Person('p2', 123456789)

print("p1 id: %s"%hex(id(p1)))

print("p2 id: %s"%hex(id(p2)))

list_test = [p1,p2]

print(set(list_test))

可以看出set调用了元素的hash方法,p1和p2的hash返回不同,就认为是不重复的元素,所以不去重

#output:

p1 id: 0x209563fabe0

p2 id: 0x209563fa910

p1 call hash method

p2 call hash method

{<__main__.person object at>, <__main__.person object at>}

set中元素的hash返回值是一样的

class Person:

def __init__(self, instance, name, identityId):

self.instance = instance

self.name = name

self.identityId = identityId

def __hash__(self):

print("%s call hash method"%self.instance)

return hash(self.identityId)

def __eq__(self, other):

print(f"{self.instance} call eq method: equal to {other.instance}")

if self.name == other.name:

return True

else:

return False

p1 = Person('p1','kelly', 123456789)

p2 = Person('p2','xia', 123456789)

p3 = Person('p3','peter', 111111111)

p4 = Person('p4','kelly', 123456789)

p5 = Person('p5','kelly.xia', 123456789)

print("p1 id: %s"%hex(id(p1)))

print("p2 id: %s"%hex(id(p2)))

print("p3 id: %s"%hex(id(p3)))

print("p4 id: %s"%hex(id(p4)))

print("p5 id: %s"%hex(id(p5)))

print(f"p1==p4:{p1==p4}")

list_test = [p1,p2,p3,p4,p5]

print(set(list_test))

p1,p2,p3,p4,p5,通过id来看是指向不同的引用的,p1和p2的hash返回值相同,所以再调用p1的eq方法,eq返回是False的,所以认为p1和p2是不重复的。而p1和p4,hash返回值是一样的,再用户p1的eq方法,返回是Ture,所以认为p1和p4是重复的,将除去p4.最后的p5,跟p1,p2的hash返回值都是一样的,所以再分别调用p1和p2的eq方法,因为eq访求返回都为False,所以认为p5分别和p1,p2是不重复的。

#output:

p1 id: 0x209564e1fd0

p2 id: 0x209564e1070

p3 id: 0x209564e1ac0

p4 id: 0x209564e1430

p5 id: 0x209564e1c40

p1 call eq method: equal to p4

p1==p4:True

p1 call hash method

p2 call hash method

p1 call eq method: equal to p2

p3 call hash method

p4 call hash method

p1 call eq method: equal to p4

p5 call hash method

p1 call eq method: equal to p5

p2 call eq method: equal to p5

{<__main__.person object at>, <__main__.person object at>, <__main__.person object at>, <__main__.person object at>}

结论

由以上得出结论:set的去重是通过两个函数__hash__和__eq__结合实现的。当两个对象的哈希值不相同时,就认为这两个对象是不同的; 当两个对象的哈希值一样时,调用__eq__方法,当返回值为True时认为这两个对象是重复的,应该去除一个。返回FALSE时,认为这两个对象不是重复的,所以不去重。

应用

利用set去重特性,我们扩展思维应用到许多需要去重的场景中去,关键就是override超类Object的__hash__和__eq__方法。

原文链接:https://blog.csdn.net/wumingxiaoyao/article/details/108921211

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值