Consider this test:
class A: def __init__(self, h): self.h = h def __hash__(self): return self.h x = A(1) y = A(2) a = {x, y} print x in a, y in a print a print "----" xh = 2 print x in a, y in a print a
Result:
True True set([<__main__.A instance at 0x10d94fd40>, <__main__.A instance at 0x10d94fd88>])
As you can see, the first object x still exists, but the in statement says that it is not. Why did this happen?
From my understanding, Set objects are implemented using hash tables, and a hash table usually has this structure:
hash_value => list of objects with this hash value another_hash_value => list of objects with this hash value
When the set answers in queries, it first computes the hash value for the argument, and then tries to find it in the corresponding list. Our set a initially looks like this:
1 => [x] 2 => [y]
Now we change the hash x and set it if there is an object. The set computes the hash value (which is now 2 ) and tries to find x in the second list and does not work - hence False .
To make things more interesting, let
a.add(x) print x in a, y in a print a
Result:
True True set([<__main__.A instance at 0x107cbfd40>, <__main__.A instance at 0x107cbfd88>, <__main__.A instance at 0x107cbfd40>])
Now we have the same object twice in the set! As you can see, there are no automatic adjustments and errors. Python is an adult language and always assumes that you know what you are doing.