Solve - TypeError: unhashable type: 'set' (Python)

avatar

Borislav Hadzhiev

Wed Apr 20 20223 min read

Solve - TypeError: unhashable type: 'set' (Python) #

The Python "TypeError: unhashable type: 'set'" occurs when we use a set as a key in a dictionary or an element in another set. To solve the error, use a frozenset instead, because set objects are mutable and unhashable.

typeerror unhashable type set

Here are 2 examples of how the error occurs.

main.py
my_set = {'apple', 'banana'} # 👇️ using set as an element in another set # ⛔️ TypeError: unhashable type: 'set' another_set = {'Alice', 'Bob', my_set} # 👇️ using set as a key in a dictionary # ⛔️ TypeError: unhashable type: 'set' my_dict = {my_set: 'fruits'}
We can't use a set as a key in a dictionary or as an element in another set because set objects are mutable and unhashable.

One way to solve the error is to use a frozenset.

main.py
my_set = frozenset({'apple', 'banana'}) another_set = {'Alice', 'Bob', my_set} print(another_set) # 👉️ {'Bob', frozenset({'banana', 'apple'}), 'Alice'} # checking if element in set print(frozenset({'apple', 'banana'}) in another_set) # 👉️ True # --------------------------------------------------------------- my_dict = {my_set: 'fruits'} print(my_dict) # 👉️ {'Bob', frozenset({'banana', 'apple'}), 'Alice'} # 👇️ accessing key in dictionary print(my_dict[frozenset({'apple', 'banana'})]) # 👉️ fruits

We used a frozenset instead of a set. The frozenset class takes an iterable as an argument.

A frozenset is a an immutable version of the Python set object, so it can be used as a key in a dictionary or an element in another set.

Notice that you have to use the same approach to access the key in the dictionary.

Alternatively, you can use another immutable type such as a tuple if that suits your use case.

main.py
my_tuple = tuple({'apple', 'banana'}) my_set = {'Alice', 'Bob', my_tuple} print(my_set) # 👉️ {'Alice', 'Bob', ('banana', 'apple')} print(tuple({'apple', 'banana'}) in my_set) # 👉️ True # ----------------------------------------------------- my_dict = {my_tuple: 'fruits'} print(my_dict) # 👉️ {('banana', 'apple'): 'fruits'} print(my_dict[tuple({'apple', 'banana'})]) # 👉️ 'fruits'

Tuple objects are immutable and are hashable.

You can also declare a tuple directly by wrapping the items in parenthesis and not square brackets.

main.py
my_tuple = ('a', 'b', 'c') print(my_tuple) # 👉️ ('a', 'b', 'c') print(type(my_tuple)) # 👉️ <class 'tuple'>

Most of the immutable built-in objects in Python are hashable, whereas mutable objects are unhashable.

If an object is hashable, then it can be used as a key in a dictionary and as an element in a set, because these data structures use the hash value internally

Hashable objects include - str, int, bool, tuple, frozenset.

Unhashable objects include - list, dict, set.

Note that tuples and frozensets are only hashable if their elements are hashable.

You can check if an object is hashable by passing it to the built-in hash() function.

main.py
print(hash('hello')) # 👉️ -1210368392134373610 # ⛔️ TypeError: unhashable type: 'set' print(hash({'a', 'b', 'c'}))

The hash function returns the hash value of the passed in object (if it has one).

Hash values are integers and are used to compare dictionary keys during a dictionary lookup.

Hashable objects have a hash value which never changes during their lifetime. This is why most immutable objects are hashable, whereas mutable ones are unhashable.

Objects like sets are mutable because the contents of a set can be changed.

main.py
my_set = {'a', 'b'} my_set.add('c') print(my_set) # 👉️ {'c', 'a', 'b'}

On the other hand, frozensets and tuples that contain primitive values are immutable (and hashable).

Dictionaries are indexed by keys and the keys in a dictionary can be any immutable type, e.g. strings or numbers.

Tuples can only be used as keys in a dictionary if they contain strings, numbers or tuples.

If a frozenset or a tuple contains mutable objects such as lists, it cannot be used as a key in a dictionary or an element in a set.

If you aren't sure what type of object a variable stores, use the type() class.

main.py
my_set = {'a', 'b'} print(type(my_set)) # 👉️ <class 'set'> print(isinstance(my_set, set)) # 👉️ True my_tuple = ('a', 'b') print(type(my_tuple)) # 👉️ <class 'tuple'> print(isinstance(my_tuple, tuple)) # 👉️ True

The type class returns the type of an object.

The isinstance function returns True if the passed in object is an instance or a subclass of the passed in class.

Use the search field on my Home Page to filter through my more than 1,000 articles.