<p dir="auto">When a type's <code class="notranslate">__eq__</code> (or <code class="notranslate">tp_richcompare</code> in C) doesn't understand the other type, it should return NotImplemented so that the other type's <code class="notranslate">__eq__</code> has a chance to be called. Unfortunately, NumPy's ArrayDesrc doesn't respect that convention and raises TypeError instead, making comparisons fragile:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; import numpy as np
&gt;&gt;&gt; class A(object):
...     def __eq__(self, other):
...         return True
... 
&gt;&gt;&gt; dt = np.dtype('i8')
&gt;&gt;&gt; A() == dt
True
&gt;&gt;&gt; dt == A()
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
TypeError: data type not understood"><pre class="notranslate"><code class="notranslate">&gt;&gt;&gt; import numpy as np
&gt;&gt;&gt; class A(object):
...     def __eq__(self, other):
...         return True
... 
&gt;&gt;&gt; dt = np.dtype('i8')
&gt;&gt;&gt; A() == dt
True
&gt;&gt;&gt; dt == A()
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: data type not understood
</code></pre></div>
<p dir="auto">It is generally considered bad practice to raise TypeError in a comparison method, and can prevent advanced uses: such as defining a custom type comparable with ArrayDescr, or simply mixing ArrayDescr with other types in e.g. a dictionary.</p>
<p dir="auto">Indeed let's say I use the standard <code class="notranslate">lru_cache</code>, then hash collisions can produce unwanted errors because of the dictionary used internally comparing the keys:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; @functools.lru_cache()
... def f(x): return str(x)
... 
&gt;&gt;&gt; 
&gt;&gt;&gt; class A(object):
...   def __hash__(self):   
...      return hash(dt)
... 
&gt;&gt;&gt; f(dt)
'int64'
&gt;&gt;&gt; f(A())
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
  File &quot;/home/antoine/34/lib/python3.4/functools.py&quot;, line 446, in wrapper
    link = cache_get(key)
TypeError: data type not understood"><pre class="notranslate"><code class="notranslate">&gt;&gt;&gt; @functools.lru_cache()
... def f(x): return str(x)
... 
&gt;&gt;&gt; 
&gt;&gt;&gt; class A(object):
...   def __hash__(self):   
...      return hash(dt)
... 
&gt;&gt;&gt; f(dt)
'int64'
&gt;&gt;&gt; f(A())
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
  File "/home/antoine/34/lib/python3.4/functools.py", line 446, in wrapper
    link = cache_get(key)
TypeError: data type not understood
</code></pre></div>
<h2 dir="auto">Summary</h2>
<p dir="auto">Make DType objects, their corresponding types, and their string names all compare unequal.</p>
<h2 dir="auto">Historical issue</h2>
<p dir="auto">For some reason, <code class="notranslate">dtype</code> objects and the numpy types they are based off of compare equal.  They don't hash equal of course, which goes against Python's docs that say</p>
<blockquote>
<p dir="auto">The only required property is that objects which compare equal have the same hash value…</p>
</blockquote>
<p dir="auto">Can we make them compare unequal?  Is there any reason for them to compare equal?</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="In [6]: np.dtype(np.float) == np.float
Out[6]: True"><pre class="notranslate"><code class="notranslate">In [6]: np.dtype(np.float) == np.float
Out[6]: True
</code></pre></div>