为何**kwargs映射与顺序不同的OrderedDict比较时结果相等?
为什么Python的有序kwargs与OrderedDict比较相等时不遵循顺序?
这个问题真的问到点子上了——很多人刚接触Python 3.6+的有序字典特性时,都会被这个相等性的“矛盾”搞懵!我来给你拆解清楚:
先理清两个关键背景
- PEP 468与kwargs的本质:PEP 468规定从Python 3.6开始,函数的关键字参数顺序会被保留,
**kwargs会成为一个有序映射。但要注意:Python 3.6里这只是CPython的实现细节,到3.7才正式成为语言规范——也就是说,从3.7开始,kwargs本质就是个普通的有序字典,而非collections.OrderedDict。 - 字典相等性的核心规则:不管字典是否有序,Python中普通字典的相等性比较逻辑从来只看键值对是否完全一致,不关心顺序。这个规则是为了向后兼容——在字典还无序的年代,判断相等就只看键值对,要是现在突然改规则,大量老代码都会出问题。
OrderedDict的相等性逻辑是特殊的
collections.OrderedDict的相等性比较是分场景的:
- 当它和**普通字典(包括kwargs)**比较时,会对齐普通字典的规则,只检查键值对是否匹配,完全不考虑顺序;
- 只有当它和另一个OrderedDict比较时,才会严格校验顺序是否一致。
用代码直观感受一下
from collections import OrderedDict def func(**kwargs): return kwargs # 按a→b的顺序传参得到kwargs kwargs_dict = func(a=1, b=2) # 两个顺序不同的OrderedDict od_ordered = OrderedDict([('a', 1), ('b', 2)]) od_reversed = OrderedDict([('b', 2), ('a', 1)]) # kwargs和OrderedDict比较,只看键值对 print(kwargs_dict == od_ordered) # 输出 True print(kwargs_dict == od_reversed) # 输出 True # 两个OrderedDict比较,会校验顺序 print(od_ordered == od_reversed) # 输出 False
如果需要校验顺序怎么办?
要是你确实需要确认kwargs的顺序和某个OrderedDict完全一致,不能直接用==,可以这样做:
# 方式1:比较items()的列表顺序 print(list(kwargs_dict.items()) == list(od_ordered.items())) # True print(list(kwargs_dict.items()) == list(od_reversed.items())) # False # 方式2:把kwargs转成OrderedDict再比较 print(OrderedDict(kwargs_dict) == od_ordered) # True print(OrderedDict(kwargs_dict) == od_reversed) # False
总结一下:核心就是普通字典的相等性逻辑为了向后兼容不看顺序,而OrderedDict只有在和同类比较时才会校验顺序,和普通字典比较时会对齐规则——这就是你看到的“矛盾”的根源。
内容的提问来源于stack exchange,提问作者wim
相关产品推荐
相关产品推荐

