TypeError: unhashable type: 'set' (Python)

avatar

Borislav Hadzhiev

Last updated: Apr 20, 2022

banner

Photo from Unsplash

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 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 parentheses 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 that 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.

Conclusion #

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.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.