使用set对python中循环的优化

set定义

日常项目中大家或多或少都使用到集合。先走走流程,介绍下set的定义:
集合(set)是一个无序的不重复元素序列。可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。

项目中常用去重手段

集合的内置方法也有很多,常用就是 使用add,remove。然后我们项目中经常会使用set进行一个去重的操作如:
a = [1,2,3,3,4,4,5,6]
print(list(set(a)))

>[1, 2, 3, 4, 5, 6]

使用set优化场景及方法

项目中偶尔会遇到这个情况,有的会这么写:
假设a表示所有员工,
b表示参加比赛的员工,
要找出没参加比赛的员工。

a = [i for i in range(20)]
b = [i for i in range(5,15)]
result = []
for j in a:
    if j not in b:
        result.append(j)
print(result)

>[0, 1, 2, 3, 4, 15, 16, 17, 18, 19]

这种可以用到集合中求差集的方式 即:

a = [i for i in range(20)]
b = [i for i in range(5,15)]
print(list(set(a)-set(b)))

>[0, 1, 2, 3, 4, 15, 16, 17, 18, 19]

我们来大致比较下两个执行时间

from time import time
t = time()
a = [i for i in range(20)]
b = [i for i in range(5,15)]
result = []
for i in range(1000000):
    for j in a:
        if j not in b:
            result.append(j)
print(time() - t)
t = time()
for i in range(1000000):
    list(set(a)-set(b))
print(time() - t)

>3.550997734069824
>1.3410418033599854

可以看到时间上是2倍多接近3倍的差距。
当然稍微扩大点 a,b 的数据,
最后是4倍左右的差距。
数据可能不是很精准,但是起码可以证明遇到类似问题可以用这个方法。

使用set的类似场景

假设a表示所有会后端员工,
b表示所有会前端员工,
如果 要找出 前后端都会的员工:

list(set(a) & set(b))

如果 要找出技术员工

list(set(a) | set(b))

set去重原理

原理: set去重是调用了内部的__hash__方法 和 __eq__方法
1、当两个变量的哈希值不相同时,就认为这两个变量是不同的
2、当两个变量哈希值一样时,调用__eq__方法,当返回值为True时认为这两个变量是同一个,应该去除一个。返回FALSE时,不去重

class Mystring:
    def __init__(self,string):
        self.string = string
    def __hash__(self):
        result = hash(id(self))
        print("%s调用了哈希方法,哈希值为:%s"%(self.string, result))
        return result
    def __eq__(self, other):
        print("%s调用了eq方法"%self)
        return self.__dict__ == other.__dict__
    def __repr__(self):
        return self.string
f1 = Mystring('aaa')
f2 = Mystring('aaa')
f3 = Mystring('ccc')
ls = [f1,f2,f3]
print(set(ls))

>
aaa调用了哈希方法,哈希值为:2616513427440
aaa调用了哈希方法,哈希值为:2616513428784
ccc调用了哈希方法,哈希值为:2616513429120
{aaa, aaa, ccc}

这里的结果不是{aaa,ccc} ,其实看哈希值其实就知道了。
原因很简单,我们是创建了f1,f2两个对象实例,这两个对象实例当然不一样了,
要实现去重可以这么实现,改下hash的方法

def __hash__(self):
        result = hash(self.string))
        print("%s调用了哈希方法,哈希值为:%s"%(self.string, result))
        return result

再次执行的结果如下:

aaa调用了哈希方法,哈希值为:-8445055340194366239
aaa调用了哈希方法,哈希值为:-8445055340194366239
aaa调用了eq方法
ccc调用了哈希方法,哈希值为:6109596974613880257
{aaa, ccc}

这里理解到了话。应用场景可以如下:
对对象进行去重,
例如 员工表中有重复数据,
字段如下: 姓名,年龄,部门,手机号。
若只认为姓名和年龄相同就是一个人,
求全部员工。

那么在hash的时候就只hash 姓名和年龄, 把eq,写死为True即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python有多种方法可以优化代码的性能,以下是一些常见的优化技巧: 1. 使用适当的数据结构:选择合适的数据结构可以提高代码的效率。例如,使用集合(set)而不是列表(list)来进行快速查找,或使用字典(dict)来实现高效的键值对操作。 2. 避免不必要的循环:尽量减少循环的次数和复杂度。可以使用列表推导式、生成器表达式或内置的高阶函数(如map、filter和reduce)来替代显式的循环。 3. 缓存计算结果:如果某个计算结果在多次使用保持不变,可以将其缓存起来,避免重复计算。可以使用装饰器(如functools.lru_cache)或自定义缓存机制来实现。 4. 使用适量的切片操作:切片操作可以在不复制整个列表或字符串的情况下获取其的一部分。但是过多的切片操作会增加内存和时间消耗,因此需要权衡使用。 5. 合理使用生成器:生成器(generator)可以节省内存,并且可以按需生成数据,而不是一次性生成全部数据。使用生成器表达式或自定义生成器函数可以提高效率。 6. 使用适量的并行处理:对于大规模计算密集型任务,可以考虑使用多线程、多进程或异步编程来并行处理,以提高代码的执行速度。 7. 使用适量的库函数:Python拥有丰富的标准库和第三方库,其许多函数经过高度优化,可以提供更高效的实现。熟悉并使用这些库函数可以减少自己编写低效代码的机会。 8. 优化算法和数据结构:对于特定的问题,选择合适的算法和数据结构是提高代码性能最重要的因素。了解不同算法和数据结构的特点,并选择适合当前场景的最佳选项。 以上只是一些常见的优化技巧,具体的优化方法还要根据具体问题和场景进行调整和优化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值