OrderedDict与普通字典行为差异:含NaN键时为何前者覆盖条目
为什么OrderedDict和你示例中的"普通字典"行为差这么多?
首先得揪出一个容易混淆的点:你代码里的normal_dict根本不是字典,而是集合(set)!里面存的是一个个(np.nan, 值)的元组,这和OrderedDict的键值对逻辑完全是两码事,这也是两者行为天差地别的核心原因。
先唠唠OrderedDict的规矩
OrderedDict是Python标准库collections里的字典子类,它最大的特点是能记住键值对的插入顺序,但它本质上还是个字典,得遵守字典的铁律:键必须是唯一的。
那为啥用np.nan当键会被覆盖?这得说字典判断键是否重复的逻辑:
- 先看哈希值:
np.nan的哈希值是固定死的(你可以自己敲hash(np.nan)试试,每次结果都一样) - 再看相等性:虽然咱都知道
np.nan != np.nan是True,但字典对np.nan有特殊约定——会把它当成同一个键来处理
所以不管你往OrderedDict里插多少次键为np.nan的条目,后面的都会把前面的给覆盖掉,普通字典也是这个德行:
import numpy as np real_normal_dict = {np.nan: 0, np.nan: 0.01, np.nan: 0.02} print(real_normal_dict) # 输出 {nan: 0.02}
再看你那个"normal_dict"
你写的normal_dict = {(np.nan, 0), (np.nan, 0.01), (np.nan, 0.02)}是集合,集合管的是整个元素的唯一性。这里的元素是元组,(np.nan, 0)和(np.nan, 0.01)虽然第一个元素都是np.nan,但第二个元素不一样啊,所以集合会把它们当成完全不同的元素,自然就全部保留下来了。
要是想让OrderedDict保留多个"类NaN"键怎么办?
如果你确实需要在OrderedDict里存多个和NaN相关的条目,直接用np.nan肯定不行,得换个思路:
- 给"NaN"加唯一标识,比如用字符串
"NaN_0"、"NaN_1"当键 - 自定义一个包装类,让每个实例的哈希值不同,同时能表示NaN的含义
举个例子:
from collections import OrderedDict import numpy as np class UniqueNaN: def __init__(self, idx): self.idx = idx def __repr__(self): return f"NaN_{self.idx}" ordered_dict = OrderedDict([(UniqueNaN(0), 0), (UniqueNaN(1), 0.01), (UniqueNaN(2), 0.02)]) print(ordered_dict) # 输出 OrderedDict([(NaN_0, 0), (NaN_1, 0.01), (NaN_2, 0.02)])
内容的提问来源于stack exchange,提问作者Tim B.
相关产品推荐
相关产品推荐

