I would like to do a brief comparison on membership tests on set
vs list
Membership tests invoke __contains__
dunder(if class implement this method). So, if we write
>>> 1 in [1,2]
it will equivalent to
>>> list.__contains__([1,2],1)
>>> True
If we do:
>>> [1,2] in [1,2,3]
>>> False #We get False instead of TypeError here
But why is above case not applicable to sets? Membership tests work in a different way in list and set. Infact list and set are implemented differently. Talking about set, they are implemented using Hash-Table
. This allow sets
to perform membership test i.e. lookups in O(1)
as compared to list
where lookups are O(n)
. So when in
is performed on a set, __contains__
try to compute the hash
of the object that need to be looked using __hash__
. Since
lists are unhashable in python, you get the error: TypeError: unhashable type: 'list'
. If you do same with list you won't get any error since list don't compute hash for membership testing.
In short membership tests cannot be performed on sets with an object that is unhashable. Generally speaking all mutable objects(list, sets, dict)
are unhashable.