Python 将具有相同哈希的两个键放入dict
上面,我创建了一个dict,其中有一个哈希冲突,两个插槽被占用Python 将具有相同哈希的两个键放入dict,python,dictionary,python-2.x,Python,Dictionary,Python 2.x,上面,我创建了一个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] 如何处理整数1的getitem?索引是如何为复杂的文
>>> one_decimal = Decimal('1')
>>> one_complex = complex(1,0)
>>> d = {one_decimal: '1D', one_complex: '1C'}
>>> len(d)
2
>>> map(hash, d)
[1, 1]
如何处理整数1
的getitem?索引是如何为复杂的文字索引解析正确的值的
Python 2.7.12/Linux。正如@CoryKramer所述,哈希相等并不意味着对象相等。Python字典可以包含任意数量的散列相等的元素,只要对象本身不相等
对您的问题的简短回答可能是,从2.7开始,Python库中的complex
类型的实现有点不完整。正如@wim所指出的,使用=
比较int
和complex
效果很好,但比较十进制
和复数
则不行。由于比较one_decimal==one_complex
由于其类型的不同,将始终返回False
,因此它们都可以在Python 2.7中的同一个字典中存在
这个问题在Python3中已经修复。我在3.5中进行实验,1个十进制数
和1个复数
是相等的。运行相同的代码段后,字典会按照预期(第一个键,最后一个值)在键one\u decimal
下包含one\u complex
的值
TL;博士
这是Py2.7的
complex
类型中的一个bug。Py3中已修复。问题仅在使用带复数的十进制时出现。Float、int等可以很好地工作,因为它们被强制用于比较
在decimal lib中,与复数进行比较的操作具体如下:
在python2中,函数实现为:
# 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
为什么len(set([1,Decimal('1'),(1+0j)])==2
是因为首先将小数与int进行比较,如果更改顺序,则会得到不同的输出:
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
另外,如果插入的顺序与文档相匹配,那么使用文本会更好,因为在最后一个值中,在集合(..)上使用文本。Python可以。比散列冲突更让我困扰的是
one_decimal==one_complex
是True
。有趣的是,正是因为这个原因,这在Py3中不起作用。更有趣的是:len(set([decimal('1'),(1+0j)]
是2,但是len set([1,decimal('1'),(1+0j)])
是1。我想你应该看看:
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
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}