python set()去重的底层原理及实例

作者:哟,写bug呢?? 时间:2021-08-30 05:04:11 

set是什么?

数学上,把set称做由不同的元素组成的集合,集合(set)的成员通常被称做集合元素(set elements)。Python把这个概念引入到它的集合类型对象里。集合对象是一组无序排列的可哈希的值。集合关系测试和union、intersection等操作符在Python里也同样如我们所预想地那样工作。

set特点

集合的元素有三个特征:

1.确定性:集合中的元素必须是确定的;

2.互异性:集合中的元素互不相同,如:集合A={1,a},则a不能等于1);

3.无序性:集合中的元素没有先后之分,如:{3,4,5}和{3,5,4}算作同一个集合。

python中集合(set)是一个无序不重复元素的集,基本功能包括关系测试和消除重复元素,还可以计算交集、差集、并集等,它与列表(list)的行为类似,区别在于set不同包括重复的值,而且set元素是无序的。

在python中可以用大括号 {} 创建集合。注意:如果要创建或初始化一个空集合,你必须用 set() 而不是 {} 。因为后者{} 作为创建一个空的字典,以后我们会介绍字典这种数据结构。

一、set去重简单实例

ls = [1,2,3,1,2]
print(set(ls))

python set()去重的底层原理及实例

我们知道对于一个列表最简单的去重方法就是直接调用set函数,利用集合元素的唯一性,就可以做到去重。但是,这个底层原理究竟是什么样的却一直半解。

且看下面剖析

二、重新set实现机制


class Foo:
   def __init__(self,name,count):
       self.name = name
       self.count = count
   def __hash__(self):
       print("%s调用了哈希方法"%self.name)
       return hash(id(self))
   def __eq__(self, other):
       print("%s调用了eq方法")
       if self.__dict__ == other.__dict__:
           return True
       else:return False
f1 = Foo('f1',1)
f2 = Foo('f2',2)
f3 = Foo('f3',3)
ls = [f1,f2,f3]
print(set(ls))

python set()去重的底层原理及实例

从上面可以看出,set方法就是去调用hash方法,然后根据哈希值一不一样就行去重判断,但是事实就是样吗?且看下面程序。


class Foo:
   def __init__(self,name,count):
       self.name = name
       self.count = count
   def __hash__(self):
       print("%s调用了哈希方法"%self.name)
       return hash(self.count)
   def __eq__(self, other):
       print("%s调用了eq方法"%self.name)
       return self.__dict__ == other.__dict__
f1 = Foo('f1',1)
f2 = Foo('f2',1)
f3 = Foo('f3',3)
ls = [f1,f2,f3]
print(set(ls))

python set()去重的底层原理及实例

我看可以看出,实际上f1,f3的哈希值是相等的,但是set并没有这么简单就判断f1,f3是重复的,而是进一步通过eq方法判断这两个值是否相等,只有相等时才会认为这两个之间实际上是同一个。为了验证上面的说法,我们来看看下面的代码。

f1 = Foo('f1',1)
f2 = Foo('f1',1)
f3 = Foo('f3',3)
ls = [f1,f2,f3]
print(set(ls))

python set()去重的底层原理及实例

可以看出去重后,只有两个元素,所以上面说法得证。

三、结论

set的去重是通过两个函数__hash__和__eq__结合实现的。
1、当两个变量的哈希值不相同时,就认为这两个变量是不同的
2、当两个变量哈希值一样时,调用__eq__方法,当返回值为True时认为这两个变量是同一个,应该去除一个。返回FALSE时,不去重

四、应用场景需求

有一个公司,现有100个员工,由于数据库不完善,使用时间比较长,里面有很多重复数据需要清除。具体需求如下:

每个员工的属性有:姓名,性别,年龄,部门。 由于年龄和部门都会发生变化,所以现在认为只要两个员工之间姓名和性别一样,就认为是同一个人。

请实现员工去重:

class Staff:
   def __init__(self,name,gender,age,department):
       self.name = name
       self.gender = gender
       self.age  = age
       self.department = department
   def __hash__(self):
       return hash(self.name+self.gender)
   def __eq__(self, other):
       return True
ls = ['zs','ls','ww','zq']
gender_list = ['man','femal']
staff_list = []
for i in range(100):
   staff_list.append(Staff(ls[i%4],gender_list[i%2],i,'class'))
print(set(staff_list))
print([(i.name,i.gender) for i in set(staff_list)])

来源:https://www.cnblogs.com/linshuhui/p/9580620.html

标签:python,set,去重
0
投稿

猜你喜欢

  • 浅析python 通⽤爬⾍和聚焦爬⾍

    2021-06-13 00:14:23
  • Tensorflow 自定义loss的情况下初始化部分变量方式

    2023-02-26 22:43:39
  • Python之string编码问题

    2021-08-28 15:25:48
  • python中matplotlib调整图例位置的方法实例

    2023-09-11 08:52:13
  • Python实现列表删除重复元素的三种常用方法分析

    2022-02-17 20:21:36
  • MySQL的添加用户的两种方法

    2012-01-29 17:50:10
  • Python中shutil模块的常用文件操作函数用法示例

    2022-10-16 07:10:08
  • 详解利用装饰器扩展Python计时器

    2023-04-08 20:32:16
  • python使用Faker进行随机数据生成

    2023-12-21 14:24:33
  • Python 使用元类type创建类对象常见应用详解

    2023-09-15 23:07:57
  • python中mediapipe库踩过的坑实战记录

    2021-03-07 13:32:47
  • python多线程使用方法实例详解

    2023-08-18 17:34:00
  • Symfony2实现从数据库获取数据的方法小结

    2023-11-14 13:56:35
  • python树的同构学习笔记

    2022-10-23 02:06:29
  • python matplotlib工具栏源码探析二之添加、删除内置工具项的案例

    2022-05-16 19:31:22
  • 详解链接的rel与target

    2007-11-05 18:25:00
  • call在Python中改进数列的实例讲解

    2021-10-12 17:17:20
  • 深入Python解释器理解Python中的字节码

    2022-04-28 18:29:33
  • PyTorch实现手写数字的识别入门小白教程

    2021-02-04 19:58:59
  • Python数据可视化 pyecharts实现各种统计图表过程详解

    2022-04-08 17:28:37
  • asp之家 网络编程 m.aspxhome.com