If I have an object that compares equal to an element of a Python set, but is not the same object, is there a reasonable way to get a reference to the object in the set? The use case would be using the set to identify and share duplicated data.
Example (Python 2.7):
>>> a = "This is a string"
>>> b = "This is a string"
>>> a is b
False
>>> a == b
True
>>> s = set((a,))
>>> b in s
True
How to get a reference to a
using b
and s
? I can think of one way, but I'm not sure if it is not implementation-dependent whether you get a
or b
. EDIT: This does not work when s has more than one element; intersection is quite naturally implemented something like [x for x in smaller_set if x in larger_set]
>>> for x in set((b,)).intersection(s): c = x
...
>>> c is a
True
Perhaps a good workaround would be to use a dict that maps each key to itself, instead of the set.
I found a similar question on python-list: Get item from set. There is a clever answer with reference to get_equivalent(container, item) (Python recipe).
The trick is to construct a wrapper object for the 'key' object, and check if wrapper is in the set using the in
operator. If the wrapper hashes equal to the key, its __eq__
method can gain access to the object in the set, and save a reference to it. An important point from the discussion is that the __eq__
method of the set elements must return NotImplemented
for unrecognized types, otherwise the wrapper's __eq__
may not get called.