Search code examples
pythondictionaryhashhashmap

Why a object of custom class can be the key of a dict, while the list can not in Python?


class MyClassA:
    def __init__(self, value=0):
        self.value = value

class MyClassB:
    def __init__(self, value=0, list_=[]):
        self.value = value
        self.list = list_
        
a = MyClassA()
b = MyClassB()
c = []

dict_ = {}
dict_[a] = 1 # No error
dict_[b] = 1 # No error
dict_[c] = 1 # TypeError: unhashable type: 'list'
  • Is the object of MyClassA / MyClassB immutable?
  • list is also a kind of object. So why it becomes unhashable? I'm quite confused about it.

Solution

  • dict keys need to be hashable, which requires implementing __hash__ method.

    By default, objects implement id-based hash function. Hash has little meaning for mutable objects though, so it is removed from implementation of built-in classes of such types. You can do the same with custom classes by assigning None to the method:

    class MyClassA:
        def __init__(self, value=0):
            self.value = value
        __hash__ = None
    dict_[MyClassA()] = 1 # TypeError: unhashable type: 'MyClassA'
    

    As to question 1 - no, you can change values of A.value and B.value and B.list so they are not immutable.

    Side notes:

    1. You probably shouldn't set list as default value of parameter - "Least Astonishment" and the Mutable Default Argument
    2. Don't call your variables with names of built-ins, e.g self.list.