今天和大家分享下python3中dict的==运算符
起因:前几天追查线上bug时,看到同事用了“==”比较两个dict是否相等,直觉告诉我这里容易出问题。 我用python3也不是很久,不太确定python是如何比较两个dict,所以针对python中dict的==实现做了下调研,和大家简单分享下。
先说结论: python3中对dict的比较忽略key的顺序,而且是迭代所有层级进行比较的。
写一个简单的测试程序:
src = {"test":{"write": "100", "read": False}, "pipe": 23}
dst = {"pipe": 23, "test":{"write": "100", "read": False}}
print(src == dst) // True
再思考一个问题,如果dict中存在list会是什么情况呢?
我们再写个例子验证下:
src = {"test":[100,200], "pipe": 23}
dst = {"pipe": 23, "test":[100,200]}
print(src == dst) // True
此时结果还是True,那如果list中又放了dict呢? 我们再来验证下
src = {"test":[{"read": False,"write": "100"}], "pipe": 23}
dst = {"pipe": 23, "test":[{"write": "100", "read": False}]}
print(src == dst) // True
此时结果还是True,那如果list中dict的顺序产生差异呢?
src = {"test":[{"read": False},{"write": "100"}], "pipe": 23}
dst = {"pipe": 23, "test":[{"write": "100"},{"read": False}]}
print(src == dst) // False
此时结果就变成了False,根据现象大概推断一下,dict逐层迭代,当value是list的时候,list的比较是有序的。 翻阅了部分python的源码,实现和预想的逻辑基本是一致的。 但是我们此处的业务逻辑,dict中如果存在list时,是要忽略顺序的,只要list中的值相等就认为两个list相等。于是写了一个简单的方法比较两个dict,忽略list的顺序。
def ignore_order_cmp(src={}, dst={}, sort_fun=None):
"""
比较两个字典或者list是否相等。
和原始比较方法的不同之处在于,对list类型先做排序,再进行比较。
params:src dst 需要比较的两组数据
params:sort_fun list类型做排序时,自定义的排序方法
"""
if isinstance(src, dict) & isinstance(dst, dict):
for key in dst:
if key not in src:
return False
for key in src:
if key in dst:
if not ignore_order_cmp(src[key], dst[key], sort_fun):
return False
else:
return False
return True
elif isinstance(src, list) & isinstance(dst, list):
if len(src) != len(dst):
return False
else:
if sort_fun is not None:
src.sort(key=sort_fun)
dst.sort(key=sort_fun)
for i in range(0, len(src)):
if not ignore_order_cmp(src[i], dst[i], sort_fun):
return False
return True
else:
return src == dst
大家在使用==判等时也要注意,phton3对不同数据类型__eq__()方法做了重载,避免踩坑。