pythonnamedtuplehashabletyped

NamedTuples, Hashable and Python


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.


Solution

  • 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