🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀!
📌 特别说明: 文中部分技术问题来源于真实生产环境及网络公开案例,均经过精挑细选与系统化整理,并结合多位一线资深架构师和工程师多年实战经验沉淀,提炼出多种经过验证的高可行性解决方案,供开发者们参考与借鉴。
欢迎 关注、收藏并订阅本专栏,持续更新的干货内容将与您同行,让我们携手精进,技术跃迁,步步高升!

全文目录:
📢 问题描述
问题来源:https://ask.csdn.net/questions/xxx
问题描述:
L1 = [258, 300, 400, 500, [100, 200], [100, 200]]
print(L1[4] == L1[5]) #True
print(L1[4] is L1[5]) #False
print(id(L1[4]))
print(id(L1[5]))
L = []
[L.append(v) for v in L1 if v not in L] #[258, 300, 400, 500, [100, 200]]
print(L)
因为L1[4]与L1[5]是不可哈希对象,所以不能用list(set(L1))这种方式去重,但是for循环遍历
出来的是列表元素对象的值,而非列表元素对象本身。L1[4]与L1[5]就像是双胞胎,虽然长得一样,却不是同一个人。
这种情况下该怎么理解操作?

📣 请知悉:如下方案不保证一定适配你的问题!
如下是针对上述问题进行专业角度剖析答疑,不喜勿喷,仅供参考:

✅️问题理解
题主遇到的是Python中包含不可哈希对象的列表去重问题。这个问题涉及Python对象比较机制、哈希特性和去重算法的深层理解。
核心技术要点:
- 对象身份vs对象值:
L1[4]
和L1[5]
是两个不同的列表对象(不同的内存地址),但包含相同的元素值 - 可哈希性限制:列表是不可哈希对象,无法直接使用
set()
进行去重 - 比较机制差异:
==
比较值相等性,is
比较对象身份,in
操作使用==
进行比较 - 去重算法选择:需要根据数据结构特点选择合适的去重策略
代码中的关键机制:
[L.append(v) for v in L1 if v not in L]
这里v not in L
使用==
比较,所以即使是不同对象但值相同的列表也能被正确识别为重复。
✅️问题解决方案
方案一:基础去重方法(当前使用的方法优化版)
def remove_duplicates_basic(lst):
"""
基础去重方法,保持原始顺序
时间复杂度:O(n²),空间复杂度:O(n)
"""
result = []
for item in lst:
if item not in result:
result.append(item)
return result
# 测试
L1 = [258, 300, 400, 500, [100, 200], [100, 200]]
result1 = remove_duplicates_basic(L1)
print("基础方法结果:", result1)
# 输出: [258, 300, 400, 500, [100, 200]]
# 列表推导式版本(您使用的方法)
def remove_duplicates_comprehension(lst):
"""使用列表推导式的去重方法"""
result = []
[result.append(v) for v in lst if v not in result]
return result
方案二:哈希化处理法(推荐)
def remove_duplicates_hashable(lst):
"""
通过转换为可哈希类型进行去重
时间复杂度:O(n),空间复杂度:O(n)
"""
def make_hashable(item):
"""将不可哈希对象转换为可哈希形式"""
if isinstance(item, list):
return tuple(make_hashable(x) for x in item)
elif isinstance(item, dict):
return tuple(sorted((k, make_hashable(v)) for k, v in item.items()))
elif isinstance(item, set):
return tuple(sorted(make_hashable(x) for x in item))
else:
return item
seen = set()
result = []
for item in lst:
hashable_item = make_hashable(item)
if hashable_item not in seen:
seen.add(hashable_item)
result.append(item)
return result
# 测试复杂数据结构
L2 = [258, 300, [100, 200], [100, 200], {'a': 1}, {'a': 1}, [1, [2, 3]], [1, [2, 3]]]
result2 = remove_duplicates_hashable(L2)
print("哈希化方法结果:", result2)
# 输出: [258, 300, [100, 200], {'a': 1}, [1, [2, 3]]]
方案三:序列化去重法
import json
import pickle
def remove_duplicates_serialize(lst):
"""
使用序列化进行去重(适用于可JSON序列化的对象)
"""
seen = set()
result = []
for item in lst:
try:
# 使用JSON序列化作为唯一标识
serialized = json.dumps(item, sort_keys=True)
if serialized not in seen:
seen.add(serialized)
result.append(item)
except (TypeError, ValueError):
# 不可JSON序列化的对象使用pickle
try:
serialized = pickle.dumps(item)
if serialized not in seen:
seen.add(serialized)
result.append(item)
except:
# 最后回退到基础比较
if item not in result:
result.append(item)
return result
# 测试
L3 = [258, 300, [100, 200], [100, 200], {"name": "张三"}, {"name": "张三"}]
result3 = remove_duplicates_serialize(L3)
print("序列化方法结果:", result3)
方案四:基于pandas的高效去重
import pandas as pd
import numpy as np
def remove_duplicates_pandas(lst):
"""
使用pandas进行高效去重(适用于大数据集)
"""
# 将列表转换为字符串表示
str_representations = []
for item in lst:
if isinstance(item, (list, dict, set, tuple)):
str_representations.append(str(sorted(item) if hasattr(item, '__iter__') and not isinstance(item, str) else item))
else:
str_representations.append(str(item))
# 使用pandas去重
df = pd.DataFrame({
'original': lst,
'str_repr': str_representations
})
# 基于字符串表示去重,保持原始顺序
deduplicated = df.drop_duplicates(subset=['str_repr'], keep='first')
return deduplicated['original'].tolist()
# 测试大数据集性能
import time
def performance_test():
"""性能测试函数"""
# 生成测试数据
large_list = []
for i in range(10000):
if i % 3 == 0:
large_list.append([i, i+1])
elif i % 3 == 1:
large_list.append(i)
else:
large_list.append([i, i+1]) # 制造重复
methods = [
("基础方法", remove_duplicates_basic),
("哈希化方法", remove_duplicates_hashable),
("序列化方法", remove_duplicates_serialize),
]
for name, method in methods:
start_time = time.time()
result = method(large_list[:1000]) # 使用较小的子集测试
end_time = time.time()
print(f"{name}: {end_time - start_time:.4f}秒, 结果长度: {len(result)}")
# performance_test()
方案五:自定义对象比较器
class DeduplicateHelper:
"""
去重助手类,支持自定义比较逻辑
"""
def __init__(self, key_func=None, hash_func=None):
"""
初始化去重助手
Args:
key_func: 自定义键提取函数
hash_func: 自定义哈希函数
"""
self.key_func = key_func or self._default_key
self.hash_func = hash_func or self._default_hash
def _default_key(self, item):
"""默认键提取函数"""
return self._make_hashable(item)
def _default_hash(self, item):
"""默认哈希函数"""
return hash(self._make_hashable(item))
def _make_hashable(self, item):
"""递归转换为可哈希类型"""
if isinstance(item, list):
return tuple(self._make_hashable(x) for x in item)
elif isinstance(item, dict):
return tuple(sorted((k, self._make_hashable(v)) for k, v in item.items()))
elif isinstance(item, set):
return tuple(sorted(self._make_hashable(x) for x in item))
else:
return item
def deduplicate(self, lst):
"""执行去重操作"""
seen = set()
result = []
for item in lst:
try:
key = self.key_func(item)
if key not in seen:
seen.add(key)
result.append(item)
except (TypeError, ValueError):
# 回退到基础比较
if item not in result:
result.append(item)
return result
# 使用示例
helper = DeduplicateHelper()
L4 = [258, 300, [100, 200], [100, 200], [1, 2, 3], [3, 2, 1]]
# 默认去重
result4 = helper.deduplicate(L4)
print("默认去重:", result4)
# 自定义比较:忽略列表元素顺序
def order_insensitive_key(item):
if isinstance(item, list):
return tuple(sorted(item))
return item
helper_custom = DeduplicateHelper(key_func=order_insensitive_key)
result5 = helper_custom.deduplicate(L4)
print("忽略顺序去重:", result5)
✅️问题延伸
1. Python对象比较机制深度解析
graph TD
A[Python对象比较] --> B[身份比较 is]
A --> C[值比较 ==]
A --> D[成员检查 in]
B --> E[比较内存地址 id()]
C --> F[调用__eq__方法]
D --> G[逐个元素比较==]
F --> H[默认实现]
F --> I[自定义实现]
H --> J[基于对象身份]
I --> K[基于对象值]
2. 不同数据类型的哈希特性
def analyze_hashability():
"""分析各种数据类型的哈希特性"""
test_items = [
42, # int - 可哈希
3.14, # float - 可哈希
"hello", # str - 可哈希
(1, 2, 3), # tuple - 可哈希
[1, 2, 3], # list - 不可哈希
{1, 2, 3}, # set - 不可哈希
{"a": 1}, # dict - 不可哈希
frozenset([1, 2, 3]), # frozenset - 可哈希
]
for item in test_items:
try:
hash_value = hash(item)
print(f"{type(item).__name__}: 可哈希, hash={hash_value}")
except TypeError:
print(f"{type(item).__name__}: 不可哈希")
# analyze_hashability()
3. 内存优化策略
class MemoryEfficientDeduplicator:
"""
内存优化的去重器
适用于大数据集处理
"""
def __init__(self, chunk_size=1000):
self.chunk_size = chunk_size
def deduplicate_large_list(self, lst):
"""分块处理大列表"""
seen = set()
result = []
for i in range(0, len(lst), self.chunk_size):
chunk = lst[i:i + self.chunk_size]
for item in chunk:
item_repr = self._get_representation(item)
if item_repr not in seen:
seen.add(item_repr)
result.append(item)
# 定期清理内存
if len(seen) > 10000:
self._optimize_memory(seen, result)
return result
def _get_representation(self, item):
"""获取对象的字符串表示"""
if isinstance(item, (list, dict, set)):
return str(sorted(item) if hasattr(item, '__iter__') else item)
return str(item)
def _optimize_memory(self, seen, result):
"""内存优化策略"""
# 这里可以实现更复杂的内存管理逻辑
pass
✅️问题预测
1. 性能瓶颈分析
import cProfile
import time
from memory_profiler import profile
def performance_benchmark():
"""
全面的性能基准测试
"""
test_data = [
([1, 2], [1, 2], [3, 4], [1, 2], 5, 6, 5), # 小数据集
list(range(1000)) + [[i, i+1] for i in range(500)] * 2, # 中等数据集
]
methods = [
("O(n²)基础方法", remove_duplicates_basic),
("O(n)哈希方法", remove_duplicates_hashable),
("序列化方法", remove_duplicates_serialize),
]
for data_name, data in zip(["小数据集", "中等数据集"], test_data):
print(f"\n{data_name}测试:")
for method_name, method in methods:
start_time = time.time()
start_memory = get_memory_usage()
result = method(data)
end_time = time.time()
end_memory = get_memory_usage()
print(f" {method_name}:")
print(f" 时间: {end_time - start_time:.4f}秒")
print(f" 内存: {end_memory - start_memory:.2f}MB")
print(f" 结果长度: {len(result)}")
def get_memory_usage():
"""获取当前内存使用量(简化版)"""
import psutil
import os
process = psutil.Process(os.getpid())
return process.memory_info().rss / 1024 / 1024 # MB
2. 边界情况处理
def handle_edge_cases():
"""处理各种边界情况"""
test_cases = [
[], # 空列表
[None, None, None], # None值
[[[], []], [[], []]], # 嵌套空列表
[float('nan'), float('nan')], # NaN值
[{'a': [1, 2]}, {'a': [1, 2]}], # 嵌套结构
[lambda x: x, lambda y: y], # 函数对象
]
for i, case in enumerate(test_cases):
print(f"测试案例{i + 1}: {case}")
try:
result = remove_duplicates_hashable(case)
print(f" 结果: {result}")
except Exception as e:
print(f" 错误: {e}")
print()
# handle_edge_cases()
3. 多线程安全性
import threading
from concurrent.futures import ThreadPoolExecutor
class ThreadSafeDeduplicator:
"""
线程安全的去重器
"""
def __init__(self):
self._lock = threading.Lock()
self._global_seen = set()
def deduplicate_parallel(self, lst, num_threads=4):
"""并行去重处理"""
chunk_size = len(lst) // num_threads
chunks = [lst[i:i + chunk_size] for i in range(0, len(lst), chunk_size)]
results = []
with ThreadPoolExecutor(max_workers=num_threads) as executor:
futures = [executor.submit(self._process_chunk, chunk) for chunk in chunks]
for future in futures:
results.extend(future.result())
# 最终去重
return self._final_deduplicate(results)
def _process_chunk(self, chunk):
"""处理单个块"""
local_seen = set()
local_result = []
for item in chunk:
item_repr = self._get_representation(item)
with self._lock:
if item_repr not in self._global_seen:
self._global_seen.add(item_repr)
local_result.append(item)
return local_result
def _get_representation(self, item):
"""获取对象表示"""
try:
if isinstance(item, list):
return tuple(item)
elif isinstance(item, dict):
return tuple(sorted(item.items()))
else:
return item
except:
return str(item)
def _final_deduplicate(self, lst):
"""最终去重步骤"""
seen = set()
result = []
for item in lst:
item_repr = self._get_representation(item)
if item_repr not in seen:
seen.add(item_repr)
result.append(item)
return result
✅️小结
核心原理解析:
您的代码[L.append(v) for v in L1 if v not in L]
能够成功去重的关键在于:
in
操作符使用==
比较:即使L1[4]
和L1[5]
是不同对象,但[100, 200] == [100, 200]
返回True
- 值相等性检测:Python的列表比较会递归比较每个元素的值,而不是比较对象身份
- 顺序保持:该方法能保持原始列表的元素顺序
最佳实践建议:
- 小数据集(<1000元素):使用基础方法
[L.append(v) for v in L1 if v not in L]
- 大数据集:使用哈希化方法
remove_duplicates_hashable()
,时间复杂度O(n) - 复杂嵌套结构:使用序列化方法或自定义比较器
- 性能敏感场景:考虑并行处理和内存优化策略
技术要点总结:
- 对象比较机制:理解
==
、is
、in
的不同比较逻辑 - 哈希特性利用:通过转换实现高效去重
- 内存管理:大数据集处理需要考虑内存效率
- 边界情况:处理None、NaN、嵌套结构等特殊情况
您当前的方法虽然简单有效,但在大数据集上性能较差。建议根据实际应用场景选择合适的优化方案。
希望如上措施及解决方案能够帮到有需要的你。
PS:如若遇到采纳如下方案还是未解决的同学,希望不要抱怨&&急躁,毕竟影响因素众多,我写出来也是希望能够尽最大努力帮助到同类似问题的小伙伴,即把你未解决或者产生新Bug黏贴在评论区,我们大家一起来努力,一起帮你看看,可以不咯。
若有对当前Bug有与如下提供的方法不一致,有个不情之请,希望你能把你的新思路或新方法分享到评论区,一起学习,目的就是帮助更多所需要的同学,正所谓「赠人玫瑰,手留余香」。
🧧🧧 文末福利,等你来拿!🧧🧧
如上问题有的来自我自身项目开发,有的收集网站,有的来自读者…如有侵权,立马删除。再者,针对此专栏中部分问题及其问题的解答思路或步骤等,存在少部分搜集于全网社区及人工智能问答等渠道,若最后实在是没能帮助到你,还望见谅!并非所有的解答都能解决每个人的问题,在此希望屏幕前的你能够给予宝贵的理解,而不是立刻指责或者抱怨!如果你有更优解,那建议你出教程写方案,一同学习!共同进步。
ok,以上就是我这期的Bug修复内容啦,如果还想查找更多解决方案,你可以看看我专门收集Bug及提供解决方案的专栏《全栈Bug调优(实战版)》,都是实战中碰到的Bug,希望对你有所帮助。到此,咱们下期拜拜。
码字不易,如果这篇文章对你有所帮助,帮忙给 bug菌 来个一键三连(关注、点赞、收藏) ,您的支持就是我坚持写作分享知识点传播技术的最大动力。
同时也推荐大家关注我的硬核公众号:「猿圈奇妙屋」 ;以第一手学习bug菌的首发干货,不仅能学习更多技术硬货,还可白嫖最新BAT大厂面试真题、4000G Pdf技术书籍、万份简历/PPT模板、技术文章Markdown文档等海量资料,你想要的我都有!
🫵 Who am I?
我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-