【问题标题】:Dictionary coercion intentional or no?字典强制是有意还是无意?
【发布时间】:2013-11-20 00:09:56
【问题描述】:

如果我写:

d = { 0:'a', 1:'b' }
d[False] = 'c'
d[True] = 'd'
print(d)

我明白了:

{ 0:'c', 1:'d' }

为什么将它们强制转换为整数?它反过来做同样的事情。

d = {False:'a', True:'b'}
d[0] = 'c'
d[1] = 'd'
print(d)

输出是:

{False:'c', True: 'd'}

可以禁用吗?是bug吗?

【问题讨论】:

标签: python python-3.x dictionary


【解决方案1】:

这是因为这些值被认为是相等的:

>>> True == 1
True
>>> 
>>> False == 0
True

并且具有相同的哈希值:

>>> hash(True), hash(1)
(1, 1)
>>> 
>>> hash(False), hash(0)
(0, 0)

因此,从字典的角度来看,True1 就像 False0 一样无法区分。

没有办法“禁用”它——你不应该在字典中使用非同质键。

在这种特定情况下,一种可能的解决方法是为 TrueFalse 保留特殊的 int 值,而不是分别为 10(假设您需要 10 作为独立键)。例如,您可以让-1 代表True-2 代表False

【讨论】:

    【解决方案2】:

    只是提供一些有关 arshajii 答案的背景。

    TrueFalse 这两个布尔值与整数有着奇怪的关系。

    一方面,它们具有不同的字符串表示形式,并且具有不同的身份:

    >>> print(True)
    True
    >>> print(1)
    1
    
    >>> True is 1
    False
    

    另一方面,它们在比较和算术中表现为整数:

    >>> True == 1
    True
    >>> True + 1
    2
    

    这种行为的原因是兼容性。很久以前,bool 类型还不存在。 “布尔”运算符复制了 C 行为,将 01 重用于“false”和“true”。

    Guido 最终实现了this didn't make much sense,并添加了我们熟悉和喜爱的常量。

    但是有一个问题。即便如此,已经有很多代码将布尔值处理为整数。如果布尔运算使用“正确”类型开始,所有这些代码都会中断。

    因此,Guido 做出了妥协。布尔值有自己的类型bool,并且显示方式与整数不同。但是在算术运算和比较中,最值得注意的是__eq____hash__,它们被视为一回事。所以旧代码可以继续工作,而新代码仍然可以利用新的bool 类型。

    也许这会在 Python 4 中发生变化。但目前,boolint 的子类,我们将不得不忍受它。

    (在相关说明中,这就是为什么 TrueFalse 使用标题大小写,而不是像其他 Python 关键字那样小写的原因之一。)

    【讨论】:

    • 它们不是别名...如果是,False is 0 将是 True。我明白你的意思,但只是为了清楚起见......
    • 已编辑和修复。这就是您在上班前使用 StackOverflow 时会发生的情况;)
    【解决方案3】:

    boolint 的子类,其representation 为“False”或“True”,但其 为0 或1。

    【讨论】:

    • 不仅仅是值——它还具有相同的散列函数。
    猜你喜欢
    • 2011-01-14
    • 2011-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多