TypeError: unhashable type: 'set' in Python [Solved]

avatar
Borislav Hadzhiev

Last updated: Apr 8, 2024
3 min

banner

# TypeError: unhashable type: 'set' in Python [Solved]

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 is an example of how the error occurs when using a set as an element in another set.

main.py
my_set = {'apple', 'banana'} # ๐Ÿ‘‡๏ธ using a set as an element in another set # โ›”๏ธ TypeError: unhashable type: 'set' another_set = {'Alice', 'Bobby', my_set}

unhashable type set

And here is another example of how the error occurs when using a set as a key in a dictionary.

main.py
my_set = {'apple', 'banana'} # ๐Ÿ‘‡๏ธ using a set as a key in a dictionary # โ›”๏ธ TypeError: unhashable type: 'set' my_dict = {my_set: 'fruits'}

using set as key in dictionary

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.

# Use a frozenset instead of a regular set

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

main.py
my_set = frozenset({'apple', 'banana'}) another_set = {'Alice', 'Bobby', my_set} print(another_set) # ๐Ÿ‘‰๏ธ {'Bobby', frozenset({'banana', 'apple'}), 'Alice'} # checking if an element is in a set print(frozenset({'apple', 'banana'}) in another_set) # ๐Ÿ‘‰๏ธ True # --------------------------------------------------------------- my_dict = {my_set: 'fruits'} print(my_dict) # ๐Ÿ‘‰๏ธ {'Bob', frozenset({'banana', 'apple'}), 'Alice'} # ๐Ÿ‘‡๏ธ accessing a key in the dictionary print(my_dict[frozenset({'apple', 'banana'})]) # ๐Ÿ‘‰๏ธ fruits

use frozenset instead of regular set

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.

# Use a tuple instead of a set object

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', 'Bobby', my_tuple} print(my_set) # ๐Ÿ‘‰๏ธ {'Alice', 'Bobby', ('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'

use tuple instead of set object

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'>

# Hashable objects vs Unhashable objects

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('bobybhadz')) # ๐Ÿ‘‰๏ธ -5394383801093474825 # โ›”๏ธ TypeError: unhashable type: 'set' print(hash({'bobby', 'hadz', 'com'}))

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, frozenset objects 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

checking type of variable

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.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

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.

Copyright ยฉ 2024 Borislav Hadzhiev