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)?
This question is related to
python
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.
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'
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.
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.
... 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.
Source: Stackoverflow.com