TypeError : Unhashable type

I am trying to get a list of list of tuples : something like [ [(1,0),(2,0),(3,0)],[(1,1),(2,1),(3,1)....]] I used this statement

set([(a,b)for a in range(3)]for b in range(3)) 

But it gives me an error

TypeError: unhashable type: 'list' 

I have 2 questions for the Python Guru's:

a) When I look at the Python definition of Hashable -

"An object is hashable if it has a hash value which never changes during its lifetime (it needs a hash() method)"

when I used dir function on the expression above

dir([(a,b)for a in range(3)]for b in range(3)) 

it seems to say the __hash__ is there. So, why do I get the error?

I was able to get [[(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1), (2, 1)], [(0, 2), (1, 2), (2, 2)]] by using the list command :

list(list((a,b) for a in range(3)) for bin range(3)) 

b)list and set both takes Iterable as parameter. How come one works(list) and another doesn't (set)?

0

6 Answers

You are creating a set via set(...) call, and set needs hashable items. You can't have set of lists. Because list's arent hashable.

[[(a,b) for a in range(3)] for b in range(3)] is a list. It's not a hashable type. The __hash__ you saw in dir(...) isn't a method, it's just None.

A list comprehension returns a list, you don't need to explicitly use list there, just use:

>>> [[(a,b) for a in range(3)] for b in range(3)] [[(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1), (2, 1)], [(0, 2), (1, 2), (2, 2)]] 

Try those:

>>> a = {1, 2, 3} >>> b= [1, 2, 3] >>> type(a) <class 'set'> >>> type(b) <class 'list'> >>> {1, 2, []} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'list' >>> print([].__hash__) None >>> [[],[],[]] #list of lists [[], [], []] >>> {[], [], []} #set of lists Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'list' 
1

TLDR:

- You can't hash a list, a set, nor a dict to put that into sets

- You can hash a tuple to put it into a set.

Example:

>>> {1, 2, [3, 4]} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'list' >>> {1, 2, (3, 4)} set([1, 2, (3, 4)]) 

Note that hashing is somehow recursive and the above holds true for nested items:

>>> {1, 2, 3, (4, [2, 3])} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'list' 

Dict keys also are hashable, so the above holds for dict keys too.

3

A list is unhashable because its contents can change over its lifetime. You can update an item contained in the list at any time.

A list doesn't use a hash for indexing, so it isn't restricted to hashable items.

The real reason because set does not work is the fact, that it uses the hash function to distinguish different values. This means that sets only allows hashable objects. Why a list is not hashable is already pointed out.

... and so you should do something like this:

set(tuple ((a,b) for a in range(3)) for b in range(3)) 

... and if needed convert back to list

You'll find that instances of list do not provide a __hash__ --rather, that attribute of each list is actually None (try print [].__hash__). Thus, list is unhashable.

The reason your code works with list and not set is because set constructs a single set of items without duplicates, whereas a list can contain arbitrary data.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like