将具有相同哈希值的两个键放入字典中

Putting two keys with the same hash into a dict

>>> one_decimal = Decimal('1')
>>> one_complex = complex(1,0)
>>> d = {one_decimal: '1D', one_complex: '1C'}
>>> len(d)
2
>>> map(hash, d)
[1, 1]

上面,我创建了一个哈希冲突的字典,占用了两个槽位。

>>> d[1]
'1D'
>>> d[1+0j]
'1C'

如何处理整数 1 的 getitem?索引如何设法为复杂的文字索引解析正确的值?

Python 2.7.12 / Linux.

正如@CoryKramer 提到的 accepted answer 所述,哈希值相等并不意味着对象相等。 Python 字典可以包含任意数量的具有相等哈希值的元素,只要对象本身不相等即可。

对您问题的简短回答可能是 complex 类型的实现在 Python 库中从 2.7 开始有点不完整。正如@wim 指出的那样,使用 == 比较 intcomplex 工作正常,但比较 Decimalcomplex 则不然。由于比较 one_decimal == one_complex 总是 return False 因为它们的类型,它们可以在 Python 2.7.

中存在于同一个字典中

此问题已在 Python 3 中修复。我在 3.5 中进行试验,其中 one_decimalone_complex 相等。在 运行 相同的片段之后,字典包含键 one_decimalone_complex 的值,正如预期的那样(第一个键,最后一个值)。

TL;DR

这是 Py2.7 的 complex 类型中的错误。在 Py3 中修复。

问题仅出现在使用 十进制复数 数字时。浮点数、整数等工作正常,因为它们被强制比较。

python3's decimal lib comparing to a complex number is handled specifically in _convert_for_comparison中:

    # Comparisons with float and complex types.  == and != comparisons
    # with complex numbers should succeed, returning either True or False
    # as appropriate.  Other comparisons return NotImplemented.
    if equality_op and isinstance(other, _numbers.Complex) and other.imag == 0:
        other = other.real

在python2中convert函数的实现是:

def _convert_other(other, raiseit=False, allow_float=False):
    """Convert other to Decimal.

    Verifies that it's ok to use in an implicit construction.
    If allow_float is true, allow conversion from float;  this
    is used in the comparison methods (__eq__ and friends).

    """
    if isinstance(other, Decimal):
        return other
    if isinstance(other, (int, long)):
        return Decimal(other)
    if allow_float and isinstance(other, float):
        return Decimal.from_float(other)

    if raiseit:
        raise TypeError("Unable to convert %s to Decimal" % other)
    return NotImplemented

为什么 len(set([1, Decimal('1'), (1+0j)])) == 2 是因为 Decimal 首先与 int 进行比较,如果你改变顺序你会得到不同的输出:

In [23]: {1, Decimal('1'), (1+0j)}
Out[23]: {(1+0j), Decimal('1')}

In [24]: {Decimal('1'),1, (1+0j)}
Out[24]: {(1+0j), Decimal('1')}

In [25]: {Decimal('1'), (1+0j), 1}
Out[25]: {1}

同时使用文字更好,因为您插入的顺序与文档匹配,因为最后一个值是 在 set(..) 上使用文字。