-1

Consider the following code:

class DummyClass:
    
    def __init__(self, name):
        self.name = name

obj_1 = DummyClass("name_1")
obj_2 = DummyClass("name_2")

my_dict = {
    obj_1: "value_1",
    obj_2: "value_2"
}

print(my_dict)

Output

{<__main__.DummyClass object at 0x7f8f6493a0b8>: 'value_1', <__main__.DummyClass object at 0x7f8f649869e8>: 'value_2'}

This code created a dictionary my_dict that has instances of the DummyClass as keys.

I would like to know if there is a magic function (e.g. __something__) that I can override in the DummyClass so that the code above would produce the following output:

{'name_1': 'value_1', 'name_2': 'value_2'}

where name_1 and name_2 are both strings, the name properties of the DummyClass instances.

I don't want to change visualization or the print, I want to actually change the key in memory.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
user1315621
  • 3,044
  • 9
  • 42
  • 86
  • Not sure why somebody would downvote. If I didn't know the name of the function that I was looking for, I could not find the answer. – user1315621 Aug 20 '21 at 18:01
  • I'm probably missing the point here, but it seems to me that `my_dict = {obj_1.name: "value_1", obj_2.name: "value_2" }` will do what you want. – BoarGules Aug 20 '21 at 18:38
  • In this particular case, yes. But is there a model general way that would allow me to write `my_dict = {obj_1: "value_1", obj_2: "value_2" }` and have the same results as `my_dict = {obj_1.name: "value_1", obj_2.name: "value_2" }`? It looks like I need to override `__repr__`. – user1315621 Aug 20 '21 at 20:36
  • 1
    It seems to me you are looking for what Delphi calls a *default attribute*: it is the RH value of the bare class instance name, which you of course have to declare, otherwise what gives `self.name` precedence over the other attributes? But Python has no mechanism that I know of for making one attribute more important than the others. I think it might be better to explain why you think you need such a mechanism. – BoarGules Aug 20 '21 at 20:51
  • 1
    Then no, there's no way to do that. The object itself is the key, there's no magic method for _"the actual value to be used as the key when this is being used as a dictionary key"_. As suggested above you should provide the context, the problem this would solve. – jonrsharpe Aug 20 '21 at 20:56

1 Answers1

1

The __repr__ method is used to generate the string that dict uses to display the keys. There is no mechanism to modify the key during dict creation or update, and no dict-specific way to modify how the key is displayed.

By default, DummyClass is inheriting its __repr__ method from object, which is what produces the <...> string. Override __repr__ to return a string built from the name attribute.

class DummyClass:

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return f"'{self.name}'"

There was a proposal to create a key-transforming dictionary, but it was rejected. It would have allowed you to write something like

d = TransformDict(lambda x: x.name)
d[obj_1] = ...
d[obj_2] = ...

and the resulting dict would behave as if 'name1' and 'name2' were the keys (while still allowing access to the original keys obj_1 and obj_2 if necessary).

chepner
  • 497,756
  • 71
  • 530
  • 681
  • This will get the printed representation right, but as pointed out in the question comments, this doesn't make the actual dictionary key a string; it just makes it look like one under `print`. – Silvio Mayolo Aug 20 '21 at 21:07
  • I didn't word this clearly enough. Either the instance of the `dict` is the key, or it isn't. `dict` doesn't provide a way to modify the key during dict creation (although see the rejected [PEP-455](https://www.python.org/dev/peps/pep-0455/), which proposed just such a mechanism), and doesn't supply a `dict`-specific hook for how the key is displayed. – chepner Aug 20 '21 at 21:11
  • Yeah, I'm not criticizing your answer at all. I just don't want the OP to think this is a total solution to their problem, given that they clarified the issue at hand in the comments. As written, this is an answer to the question posed. There's just additional context in the comments that I don't want OP to miss. – Silvio Mayolo Aug 20 '21 at 21:12
  • I've tried to clarify the answer in a way that addresses the original intent. – chepner Aug 20 '21 at 21:16
  • Thank you. So, in conclusion, will using `__repr__` make the keys strings if the `__repr__` function returns a string? – user1315621 Aug 21 '21 at 01:09
  • Yes. `dict.__repr__` uses the `__repr__` method of each key and value to construct the representation of the `dict`. – chepner Aug 21 '21 at 15:45