0

I have the following: I see the following object has __hash__ attribute

a=[1,2,3]

>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delsli
ce__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getit
em__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__',
 '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__r
educe__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__'
, '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'a
ppend', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'
]

>>> dict1={a:'55'}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Q:even though it has __hash__ attribute, still it cannot be used as key.Why?

fsociety
  • 977
  • 3
  • 12
  • 23
  • 1
    Possible duplicate of [Python, TypeError: unhashable type: 'list'](http://stackoverflow.com/questions/19371358/python-typeerror-unhashable-type-list) – Sangeon Park Feb 01 '17 at 05:53
  • 1
    Hint: `print(a.__hash__)` – PM 2Ring Feb 01 '17 at 05:53
  • The question that Sangeon Park linked isn't an exact dupe of this question, but I think it contains a lot of very relevant information. For further info, please see the [`__hash__` docs](https://docs.python.org/3/reference/datamodel.html#object.__hash__). – PM 2Ring Feb 01 '17 at 05:57
  • 1
    You might be wondering "why does `list` even have a `__hash__` attribute if it's not hashable?". Well, it inherits that attribute from the `object` class, and to remove an inherited attribute violates the [Liskov substitution principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle), the 'L' in [SOLID](https://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29). – PM 2Ring Feb 01 '17 at 06:08
  • 1
    FWIW, it is actually possible to create your own mutable object that implements `__hash__`, but if that hash method depends on any of the mutable attributes of the instance then you **must not** mutate those attributes if you use the instance as a dict key (or set element), otherwise Bad Things happen. – PM 2Ring Feb 01 '17 at 06:12

1 Answers1

3

Did you try looking at the value of the attribute?

>>> print(a.__hash__)
None

Just because something has a __hash__ attribute doesn't mean it's hashable; the __hash__ attribute has to be a callable that actually hashes it (instead of, e.g., raising an exception).

BrenBarn
  • 242,874
  • 37
  • 412
  • 384