0

Is there a built-in way to get dictionary key in which object is placed?

class Example():
    def do_black_magic(self):
        return __builtin_magic__(self)

map = {0: Example()}
map[0].do_black_magic() # -> 0

map[1] = map.pop(0)
ma[1].do_black_magic() # -> 1
  • 1
    no, iterate through the dict, or create a reverse mapping. Values are not necessarily unique in general, and dictionaries are a "one way mapping" of keys to values. – Paritosh Singh Sep 13 '19 at 10:40
  • construct the Example() with the key? map = {x: Example(x) for x in range(10)} – Sam Daniel Sep 13 '19 at 10:44
  • 2
    Sounds like what you want is some sort of bi-directional hash table. Check out this `bidict` class: https://stackoverflow.com/a/21894086/1622937 – j-i-l Sep 13 '19 at 11:01
  • 1
    Possible duplicate of [How to implement an efficient bidirectional hash table?](https://stackoverflow.com/questions/3318625/how-to-implement-an-efficient-bidirectional-hash-table) – j-i-l Sep 13 '19 at 11:03

1 Answers1

1

You could implement a dictionary that manages a reverse mapping, but you'd have to be very careful with what you use as keys in the reverse mapping.

I very naively used the default string representation of the object for the sake of the example. You will for sure want to use something else (ie implement __eq__ and __hash__ in your Example class).

from collections import UserDict

class MyDict(UserDict):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._reverse_mapping = {}

    def __setitem__(self, key, value):
        super().__setitem__(key, value)
        self._reverse_mapping[str(value)] = key

    def get_reversed_mapping(self, value):
        return self._reverse_mapping[str(value)]


class Example: pass


my_dict = MyDict()

obj_1 = Example()
my_dict[1] = obj_1
print(my_dict.get_reversed_mapping(obj_1))

obj_2 = Example()
my_dict[2] = obj_2
print(my_dict.get_reversed_mapping(obj_2))

Outputs

1
2

I can't stress this enough: Do not use the string representation of the object. It will fail miserably if that representation changes:

class Example:
    def __init__(self, n):
        self.n = n

    def __str__(self):
        return str(self.n)


my_dict = MyDict()
obj = Example(1)
my_dict[1] = obj
print(my_dict.get_reversed_mapping(obj))
obj.n = 2
print(my_dict.get_reversed_mapping(obj))

Outputs

1
Traceback (most recent call last):
    return self._reverse_mapping[str(value)]
KeyError: '2'
DeepSpace
  • 78,697
  • 11
  • 109
  • 154