<br><br><div class="gmail_quote">On Thu, Sep 1, 2011 at 10:32 AM, Richard D. Moores <span dir="ltr">&lt;<a href="mailto:rdmoores@gmail.com">rdmoores@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
The glossary defines &quot;hashable&quot; as:<br>
<br>
hashable<br>
An object is hashable if it has a hash value which never changes<br>
during its lifetime (it needs a __hash__() method), and can be<br>
compared to other objects (it needs an __eq__() method). Hashable<br>
objects which compare equal must have the same hash value.<br>
<br>
Hashability makes an object usable as a dictionary key and a set<br>
member, because these data structures use the hash value internally.<br>
<br>
<br>
All of Python’s immutable built-in objects are hashable, while no<br>
mutable containers (such as lists or dictionaries) are. Objects which<br>
are instances of user-defined classes are hashable by default; they<br>
all compare unequal, and their hash value is their id().<br>
<br>
I&#39;m trying to write a general test for hashability. How can I test if<br>
an object has both a  __hash__() method and an __eq__() method?<br>
<br>
Thanks,<br>
<br>
Dick Moores<br>
_______________________________________________<br>
Tutor maillist  -  <a href="mailto:Tutor@python.org">Tutor@python.org</a><br>
To unsubscribe or change subscription options:<br>
<a href="http://mail.python.org/mailman/listinfo/tutor" target="_blank">http://mail.python.org/mailman/listinfo/tutor</a><br>
</blockquote></div><br><div><br></div><div><br></div><div>To test for a method within any object you can just go like this:</div><div><br></div><div><div>&gt;&gt;&gt; a = ()</div><div>&gt;&gt;&gt; type(a)</div><div>&lt;type &#39;tuple&#39;&gt;</div>
<div>&gt;&gt;&gt; if &#39;__hash__&#39; in dir(a): print True</div><div>True</div></div><div><div>&gt;&gt;&gt; if &#39;__eq__&#39; in dir(a): print True</div><div>True</div><div>&gt;&gt;&gt; </div></div><div><br></div><div>
But, I think the method you are approaching it from will only test for hashability. For example, you could do this:</div><div><br></div><div><div><div>&gt;&gt;&gt; a = []</div><div>&gt;&gt;&gt; type(a)</div><div>&lt;type &#39;list&#39;&gt;</div>
<div>&gt;&gt;&gt; if &#39;__hash__&#39; in dir(a): print True</div><div>True</div></div><div><div>&gt;&gt;&gt; if &#39;__eq__&#39; in dir(a): print True</div><div>True</div><div>&gt;&gt;&gt; </div></div></div><div><br></div>
<div>and then do this:</div><div><br></div><div><div>&gt;&gt;&gt; b = []</div><div>&gt;&gt;&gt; c = {b:1}</div><div><br></div><div>Traceback (most recent call last):</div><div>  File &quot;&lt;pyshell#36&gt;&quot;, line 1, in &lt;module&gt;</div>
<div>    c = {b:1}</div><div>TypeError: unhashable type: &#39;list&#39;</div></div><div><br></div><div>here is the dir for a list (not hashable):</div><div><br></div><div><div>&gt;&gt;&gt; dir(b)</div><div>[&#39;__add__&#39;, &#39;__class__&#39;, &#39;__contains__&#39;, &#39;__delattr__&#39;, &#39;__delitem__&#39;, &#39;__delslice__&#39;, &#39;__doc__&#39;, &#39;__eq__&#39;, &#39;__format__&#39;, &#39;__ge__&#39;, &#39;__getattribute__&#39;, &#39;__getitem__&#39;, &#39;__getslice__&#39;, &#39;__gt__&#39;, &#39;__hash__&#39;, &#39;__iadd__&#39;, &#39;__imul__&#39;, &#39;__init__&#39;, &#39;__iter__&#39;, &#39;__le__&#39;, &#39;__len__&#39;, &#39;__lt__&#39;, &#39;__mul__&#39;, &#39;__ne__&#39;, &#39;__new__&#39;, &#39;__reduce__&#39;, &#39;__reduce_ex__&#39;, &#39;__repr__&#39;, &#39;__reversed__&#39;, &#39;__rmul__&#39;, &#39;__setattr__&#39;, &#39;__setitem__&#39;, &#39;__setslice__&#39;, &#39;__sizeof__&#39;, &#39;__str__&#39;, &#39;__subclasshook__&#39;, &#39;append&#39;, &#39;count&#39;, &#39;extend&#39;, &#39;index&#39;, &#39;insert&#39;, &#39;pop&#39;, &#39;remove&#39;, &#39;reverse&#39;, &#39;sort&#39;]</div>
</div><div><br></div><div>here is the dir for a tuple (hashable):</div><div><br></div><div><div>&gt;&gt;&gt; dir(())</div><div>[&#39;__add__&#39;, &#39;__class__&#39;, &#39;__contains__&#39;, &#39;__delattr__&#39;, &#39;__doc__&#39;, &#39;__eq__&#39;, &#39;__format__&#39;, &#39;__ge__&#39;, &#39;__getattribute__&#39;, &#39;__getitem__&#39;, &#39;__getnewargs__&#39;, &#39;__getslice__&#39;, &#39;__gt__&#39;, &#39;__hash__&#39;, &#39;__init__&#39;, &#39;__iter__&#39;, &#39;__le__&#39;, &#39;__len__&#39;, &#39;__lt__&#39;, &#39;__mul__&#39;, &#39;__ne__&#39;, &#39;__new__&#39;, &#39;__reduce__&#39;, &#39;__reduce_ex__&#39;, &#39;__repr__&#39;, &#39;__rmul__&#39;, &#39;__setattr__&#39;, &#39;__sizeof__&#39;, &#39;__str__&#39;, &#39;__subclasshook__&#39;, &#39;count&#39;, &#39;index&#39;]</div>
</div><div><br></div><div>What I would probably do though is use the built in method hash</div><div><br></div><div>so you could do something like this:</div><div><br></div><div><div>&gt;&gt;&gt; a = &#39;a&#39;</div><div>
&gt;&gt;&gt; b = ()</div><div>&gt;&gt;&gt; c = []</div><div>&gt;&gt;&gt; print type(a), type(b), type(c)</div><div>&lt;type &#39;str&#39;&gt; &lt;type &#39;tuple&#39;&gt; &lt;type &#39;list&#39;&gt;</div><div>&gt;&gt;&gt; print hash(a)</div>
<div>-468864544</div><div>&gt;&gt;&gt; print hash(b)</div><div>3527539</div><div>&gt;&gt;&gt; print hash(c)</div><div><br></div><div>Traceback (most recent call last):</div><div>  File &quot;&lt;pyshell#48&gt;&quot;, line 1, in &lt;module&gt;</div>
<div>    print hash(c)</div><div>TypeError: unhashable type: &#39;list&#39;</div><div>&gt;&gt;&gt; </div></div><div><br></div><div><br></div><div>You can then use try, except to catch it on an as needed basis.</div><div><br>
</div><div>Not sure if this answers the question you are asking though.</div>