You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OrderedDict与普通字典行为差异:含NaN键时为何前者覆盖条目

为什么OrderedDict和你示例中的"普通字典"行为差这么多?

首先得揪出一个容易混淆的点:你代码里的normal_dict根本不是字典,而是集合(set)!里面存的是一个个(np.nan, 值)的元组,这和OrderedDict的键值对逻辑完全是两码事,这也是两者行为天差地别的核心原因。

先唠唠OrderedDict的规矩

OrderedDict是Python标准库collections里的字典子类,它最大的特点是能记住键值对的插入顺序,但它本质上还是个字典,得遵守字典的铁律:键必须是唯一的。

那为啥用np.nan当键会被覆盖?这得说字典判断键是否重复的逻辑:

  1. 先看哈希值:np.nan的哈希值是固定死的(你可以自己敲hash(np.nan)试试,每次结果都一样)
  2. 再看相等性:虽然咱都知道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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:08:00