当前位置:首页>python>你的代码里有多少重复?一个被低估的Python神器

你的代码里有多少重复?一个被低估的Python神器

  • 2026-09-20 13:42:41
你的代码里有多少重复?一个被低估的Python神器
★

Python 集合(set)实战指南:告别低效循环,写出高性能优雅代码,面向 Python 开发者,从基础用法到性能对比、实战场景、踩坑总结,全部代码可直接复制运行,帮你彻底吃透 set。


一、开篇:从一段低效代码说起

你是否还在用多层循环做去重、查重复、比对列表? 先看一段非常典型的"新手写法":

# 低效查找重复元素:O(n²) 复杂度some_list = ['a', 'b', 'c', 'b', 'd', 'm', 'n', 'n']duplicates = []for value in some_list:if some_list.count(value) > 1and value notin duplicates:        duplicates.append(value)print(duplicates)  # ['b', 'n']

问题很明显:

  • 性能差:count + in 双重遍历,O(n²) 复杂度
  • 代码冗余:7 行只做一件小事
  • 不 Pythonic:完全没用到内置数据结构优势

用 Counter + 集合推导式,O(n) 实现:

from collections import Countersome_list = ['a', 'b', 'c', 'b', 'd', 'm', 'n', 'n']counts = Counter(some_list)                          # 一次遍历统计所有频次duplicates = {x for x, c in counts.items() if c > 1}print(duplicates)  # {'b', 'n'}
★

⚠️ 常见误区:{x for x in some_list if some_list.count(x) > 1} 看起来是"一行",但内部每次仍调用 count 遍历全表,复杂度依然是 O(n²),并没有解决性能问题。真正的优化是先用 Counter 一次性统计频次,再做过滤。


二、集合基础:核心特性与创建

set 是 Python 内置无序、不重复、可变的哈希集合,是处理唯一性、成员判断的最优结构。

2.1 四种创建方式

# 1. 直接创建s1 = {1, 2, 3}# 2. 从可迭代对象创建(自带去重)s2 = set([1, 2, 2, 3, 3])s3 = set('pythonnn')# 3. 空集合(重要坑点)empty_set = set()   # 正确empty_dict = {}     # 这是字典!# 4. 集合推导式s4 = {x for x in range(10) if x % 2 == 0}

2.2 核心特性

  • 自动去重
  • 无序(不支持下标索引)
  • 元素必须可哈希(int/str/tuple 等不可变类型)
  • 查找/删除/添加平均 O(1)

三、高频实战场景(开发必备)

场景 1:列表快速去重

lst = [1, 3, 2, 3, 1, 4]unique_lst = list(set(lst))print(unique_lst)

有序去重(Python 3.7+):

lst = ['a', 'b', 'c', 'b', 'd', 'a']ordered_unique = list(dict.fromkeys(lst))print(ordered_unique)  # ['a', 'b', 'c', 'd']

场景 2:海量数据存在性判断(性能碾压 list)

import timebig_list = list(range(1_000_000))big_set = set(big_list)target = 999999# list 查找 O(n)t1 = time.time()target in big_listprint('list 耗时:', time.time() - t1)# set 查找 O(1)t2 = time.time()target in big_setprint('set 耗时:', time.time() - t2)
★

数据量越大,set 优势越恐怖,适合用户 ID、权限、黑名单校验。

场景 3:交集(共同元素)

valid_colors = {'red', 'blue', 'green', 'black'}user_input = {'red', 'brown', 'blue'}valid = valid_colors & user_input# valid = valid_colors.intersection(user_input)print(valid)  # {'red', 'blue'}

场景 4:差集(找出差异/非法内容)

invalid = user_input - valid_colorsprint(invalid)  # {'brown'}

场景 5:并集(合并去重)

tag1 = {'Python', '后端', '开发'}tag2 = {'Python', '数据分析', '可视化'}all_tags = tag1 | tag2print(all_tags)

场景 6:对称差集(只在一边出现的元素)

a = {1, 2, 3}b = {3, 4, 5}print(a ^ b)  # {1, 2, 4, 5}

四、集合常用方法速查表

方法
运算符
用途
add(x)
—
添加元素
remove(x)
—
删除元素,不存在报错
discard(x)
—
删除元素,不存在不报错
pop()
—
随机弹出一个元素
clear()
—
清空集合
intersection&
交集
union|
并集
difference-
差集
symmetric_difference^
对称差集
issubset<=
是否为子集
issuperset>=
是否为超集

五、高频踩坑与解决方案

坑 1:不能存 list / dict 等可变类型

# 报错# s = {[1,2], [3,4]}# 正确:转 tuples = {(1, 2), (3, 4)}

坑 2:{} 不是空集合,是空字典

print(type({}))     # <class 'dict'>print(type(set()))  # <class 'set'>

坑 3:set 无序,不要依赖顺序写逻辑

需要有序且唯一 → 使用 dict.fromkeys 或 list + set 组合。


六、进阶:不可变集合 frozenset

不可变、可哈希,可做字典 key 或集合元素。

fs = frozenset([1, 2, 3])d = {fs: "可作为key"}s = {fs, frozenset([4, 5])}

适用场景:配置常量、缓存 key、嵌套集合。


七、总结:什么时候优先用 set?

  • 需要去重
  • 需要快速判断元素是否存在
  • 需要做交集/差集/并集运算
  • 需要保证元素唯一性

一句话:凡是和"唯一性、存在性、集合运算"相关的逻辑,优先想到 set,性能与代码简洁度直接上一个档次。

最新文章

随机文章