将具有相同哈希值的两个键放入字典中
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 指出的那样,使用 ==
比较 int
和 complex
工作正常,但比较 Decimal
和 complex
则不然。由于比较 one_decimal == one_complex
总是 return False
因为它们的类型,它们可以在 Python 2.7.
中存在于同一个字典中
此问题已在 Python 3 中修复。我在 3.5 中进行试验,其中 one_decimal
和 one_complex
相等。在 运行 相同的片段之后,字典包含键 one_decimal
下 one_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(..) 上使用文字。
>>> 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 指出的那样,使用 ==
比较 int
和 complex
工作正常,但比较 Decimal
和 complex
则不然。由于比较 one_decimal == one_complex
总是 return False
因为它们的类型,它们可以在 Python 2.7.
此问题已在 Python 3 中修复。我在 3.5 中进行试验,其中 one_decimal
和 one_complex
相等。在 运行 相同的片段之后,字典包含键 one_decimal
下 one_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}
同时使用文字更好,因为您插入的顺序与文档匹配,因为最后一个值是