Reputation: 43
I want to use an object as a key in a dictionary, but I want to lose the identity of the key to that of one of the object's fields. Overloading the hash and equality functions is trivial, and works as expected, but I was not able to find a solution for the key to be inserted with the field's type inside the dictionary.
Here is an example:
class Foo:
def __init__(self, val):
self.val = val
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.val == other.val
elif isinstance(other, int):
return self.val == other
else:
return False
def __hash__(self):
return hash(self.val)
# this is false
print Foo(3) == Foo(4)
# this is true
print Foo(3) == Foo(3)
# this is true
print Foo(3) == 3
Now, if I use a Foo instance as a key, the identity of the key is a Foo instance (as expected):
d = {}
d[Foo(3)] = 'bar'
>>> print(d)
{<__main__.Foo instance at 0x7fe47b8e0a70>: 'bar'}
What I would like is d[Foo(3)]
to actually exchange the key for the int type 3
such that there is no trace of the Foo class inside the dictionary:
d = {}
d[Foo(3)] = 'bar'
>>> print(d)
{3: 'bar'}
Edit 1: as a clarification, note that I do not care about the behavior of the print statement, what I want is, as someone put it below, my "Foo" instance to automagically become an "int" when used as a key.
Edit 2: In my case the field is a string and the dictionary eventually gets dumped to a json file, which can only take string and scalar types. I do not want to have to explicitly cast my object to string since it is a string.
Edit 3: Unfortunately, it looks like what I'm after has already been proposed (and rejected): PEP-455
Upvotes: 2
Views: 134
Reputation: 530960
Explicit is better than implicit.1 In this case, it means using an integer as the key rather than expecting an object to "become" an integer in this context.
Take RickyA's advice.
d[Foo(3).val] = 'bar'
1 Second item in the Zen of Python
Upvotes: 3