在 Python 中使用 None 作为字典键是不是合理?

Posted

技术标签:

【中文标题】在 Python 中使用 None 作为字典键是不是合理?【英文标题】:Is it reasonable to use None as a dictionary key in Python?在 Python 中使用 None 作为字典键是否合理? 【发布时间】:2011-10-25 04:39:16 【问题描述】:

None 似乎可以用作字典键,但我想知道这是否会在以后导致麻烦。例如,这有效:

>>> x='a':1, 'b':2, None:3
>>> x
'a': 1, None: 3, 'b': 2
>>> x[None]
3

我使用的实际数据是教育标准。每个标准都与一个内容区域相关联。一些标准也与内容子领域相关联。我想制作一个contentArea:contentSubArea:[standards] 形式的嵌套字典。其中一些 contentSubArea 键将为 None。

特别是,我想知道如果我寻找一个在某些时候不存在的密钥,或者类似的意外情况,这是否会导致混乱。

【问题讨论】:

导致麻烦的是使用NaN 作为键。它具有欺骗性,因为它是可散列的,但不等于自身。也就是说:float('nan') == float('nan') 在我尝试过的两个 Python 实现中返回 False。如果您将它用作字典中的键,它不会引发异常,并且当且仅当它是相同的 NaN 对象(具有相同的 id(..))时,将其用作索引才有效——尽管这可能依赖于实现。所以它可能会按预期工作一段时间,然后失败。这些麻烦都不会影响None,即使只是因为只有一个None 【参考方案1】:

任何可散列值都是有效的 Python 字典键。因此,None 是一个完全有效的候选者。查找不存在的键时没有混淆 - 存在 None 作为键不会影响检查是否存在另一个键的能力。例如:

>>> d = 1: 'a', 2: 'b', None: 'c'
>>> 1 in d
True
>>> 5 in d
False
>>> None in d
True

没有冲突,您可以像平常一样进行测试。它不应该给你带来问题。标准的 1 对 1 键值关联仍然存在,因此 None 键中不能有多个东西,但使用 None 作为键本身不应该造成问题。

【讨论】:

问题是当你想按键排序字典时。我想对于这种情况,您需要创建特殊对象来替换 None 类型。【参考方案2】:

None 没有任何特殊之处,它只是另一个 python 值。它唯一的区别是它恰好是一个没有指定任何其他返回值的函数的返回值,它也恰好是一个常见的默认值(例如dict.get()的默认arg)。

使用这样的键不会导致任何运行时冲突,但您应该问问自己,这是否真的是用于键的有意义值。从阅读代码和理解其作用的角度来看,将指定实例用于特殊值通常更有帮助。比如:

NoSubContent = SubContentArea(name=None)

"contentArea": 
    NoSubContent:[standards], 
     SubContentArea(name="Fruits"): ['apples', 'bananas']

【讨论】:

这种方法不只是将 None 的使用降低了一个级别吗?我在想只设置有意义的值可能会更好。那么 None 表示空数据,error 表示数据有问题(假设有适当的验证和要求,例如允许 null 或要求 not null)。 就像我说的,None 并没有什么特别之处,如果很明显这意味着什么,我认为我会毫不犹豫地将它用作 dict 中的键听写;但是如果 dict 是相当异构的,或者在程序的很大一部分中是可见的;为键的类型添加一些含义可能会有所帮助。这与其说是避免None 值的问题,不如说是选择一个比None 能更好地解释自己的类型的统一值。 我接受了 gddc 的回答,但也赞成这个回答。到目前为止,使用 None 是有效的,但我可以看到在特定上下文中创建特定键来表示 None 的优势。 我不认为你想'用一个键来代表None'那是荒谬的,如果你需要代表None,就使用None。另一方面,您可能会使用None 来表示特定应用程序域的退化情况,或者这可能会造成混淆,因此您使用另一个类的指定实例来表示该退化情况。 None 在任何可能的方面类似于 C/C++ 中存在的 'void' 数据类型。【参考方案3】:

在我看来,更大的,后来的问题是这个。如果您的进程正在创建对并且某些对具有“None”键,那么它将覆盖所有以前的 None 对。你的字典会默默地抛出值,因为你有重复的 None 键。没有?

【讨论】:

我打算使用 None 作为键,想“我会看看 *** 对此有什么看法”这说服了我不要 如果你有一个“5”键怎么办。那不会被默默地覆盖吗?为什么 None 对象有这种特殊性? @MadPhysicist - 不是。字典始终是一对一的键值对容器。重新分配 any 键将替换之前键中的任何内容。 @g.d.d.c.我同意。我的观点是None5 一样有效。如果方便的话,没有理由不使用它。【参考方案4】:

有趣的是,即使这样也有效:

d = None: 'None'

In [10]: None in d
Out[10]: True

【讨论】:

【参考方案5】:

你想要麻烦吗?我们开始:

>>> json.loads(json.dumps(None:None))
u'null': None

所以,如果您确实使用 None 作为密钥,最好远离 json。您可以通过自定义 (de/)serializer 对此进行修补,但我建议您首先不要使用 None 作为键。

【讨论】:

【参考方案6】:

jsonify 不支持带有 None 键的字典。

From Flask import jsonify

def json_():
    d = None: 'None'
    return jsonify(d)

这会引发错误:TypeError: '

【讨论】:

以上是关于在 Python 中使用 None 作为字典键是不是合理?的主要内容,如果未能解决你的问题,请参考以下文章

Python 为啥list不能作为字典的key

python字典及基础操作

python如何判断变量是不是为none?

猿课python 第三天

Python中的字典

python字典