This code shows that frozensets aren't really immutable. The same frozenset is printed twice, with different content. Buggy functions are set_contains, set_remove and set_discard, all in Objects/setobject.c class bad: def __eq__(self, other): global f2 f2 = other print_f2() s1.add("querty") return self is other def __hash__(self): return hash(f1) def print_f2(): print(id(f2), repr(f2)) f1 = frozenset((1, 2, 3)) s1 = set(f1) s1 in {bad()} print_f2()
I'm not sure that I care about this one. The only way to pull it off it is to intentionally try to mutate the frozenset. Will look at it along with the others though.
I have found this in Python 3.1.2 documentation: "Note, the elem argument to the __contains__(), remove(), and discard() methods may be a set. To support searching for an equivalent frozenset, the elem set is temporarily mutated during the search and then restored. During the search, the elem set should not be read or mutated since it does not have a meaningful value." I seems to me that this is precisely what happens in this code. Now we might argue whether this is an acceptable state of affairs, but at least it's a documented behavior (and people shouldn't write equality predicates like this anyway. ;)).