成员资格测试中的numpy dtype给出了奇怪的结果

时间:2017-07-16 03:14:25

标签: python numpy

在编写一些涉及numpy的程序时,我发现成员资格测试对numpy dtype对象没有预期效果。具体而言,set的结果是意料之外的,但不是listtuple

import numpy as np
x = np.arange(5).dtype
y = np.int64
print(x in {y}, x in (y,), x in [y])

结果为False True True

在Python 2.7和3.6中都发现了这一点,安装了numpy 1.12.x。

知道为什么吗?

更新

看起来dtype对象不尊重Python中关于散列的一些假设。

http://www.asmeurer.com/blog/posts/what-happens-when-you-mess-with-hashing-in-python/

https://github.com/numpy/numpy/issues/5345

谢谢@ ser2357112和@Fabien

2 个答案:

答案 0 :(得分:2)

dtype对象的__hash____eq__实现非常糟糕。在其他问题中,__hash____eq__实现彼此不一致。你在这里看到了它的影响。

dtype __hash____eq__的其他一些问题是

  • dtype对象实际上是以影响__hash____eq__的方式可变的,这对于可散列对象永远不应该是真实的。 (具体来说,您可以重新分配结构化dtype的names。)
  • dtype等式不可传递。例如,对于问题中的xy,我们有x == yx == 'int64',但y != 'int64'
  • dtype __eq__在应该返回TypeError时会引发NotImplemented

您可以提交错误报告,但查看与这些方法相关的existing bug reports,不太可能修复。设计过于混乱,人们已经依赖于破碎的部分。

答案 1 :(得分:0)

区别在于sets如何在Python中实现in关键字。

  

列表只是检查每个对象,检查是否相等。设置第一个哈希对象。

     

different meaning of the 'in' keyword for sets and lists

这是因为套装必须保证唯一性。但是你的对象并不等同:

>>> x
dtype('int64')
>>> y
<class 'numpy.int64'>

散列它们可能会产生不同的结果。