Consider the following code:
#!/usr/bin/env python3.7
from typing import NamedTuple, Set
class Person(NamedTuple):
name: str
fred: Set[str]
p = Person("Phil", set())
print(p)
my_dict = {}
my_dict[p] = 10
print(my_dict)
which produces this error
Traceback (most recent call last):
File "./temp.py", line 14, in <module>
my_dict[p] = 10
TypeError: unhashable type: 'set'
In this case, it's sample code, and I have simplified it lots, so its
quite easy to see where the error comes from. typed.NamedTuple
obviousl calculates its hash based on all of its instances variables
and one of them is a set. When I discovered this, however, it was
painful to track down.
So, my question is, why is the error message showing this? Should it
not be TypeError: unhashable type: 'Person'
. And why is the
traceback not coming from the bowels of python somewhere where the
error actually is.
NamedTuple
is based on the tuple
class. See collections.namedtuple()
The hash of a tuple
is the combined hash of all the elements. See tupleobject.c
Since set
is unhashable it is not possible to hash a tuple
or NamedTuple
containing a set
.
And since the hashing of a set is implemented in C you don't see the traceback