+ 12
How is it possible to assign with == [solved]
I am confused, that this code works https://code.sololearn.com/cVsQ5fyZqtc5
17 Answers
+ 11
Okay, so based on the links provided by Jayakrishna🇮🇳 and some more experimentation I think this is what is going on.
MappingProxyType is merely a wrapper. There is no way to change the underlying dictionary via this wrappper. That is why proxy cannot be changed. But when you change the underlying dictionary this affects the view created with the wrapper. So any change to orig means a change to proxy. Because proxy is merely a wrapper for orig it is orig that is sent to the __eq__() function. So the reason that proxy changed despite being immutable is that despite the fact that the function is called on proxy it is actually executed on orig. And proxy is only immutable in the sense that you cannot change the underlying dictionary via proxy. But the underlying dictionary can still be changed directly.
So when using MappingProxyType you have to be careful not to change the underlying dictionary if you want the view to remain unchanged.
+ 5
A simpler code with the same weird effect:
https://code.sololearn.com/cy8RD8E722CX/?ref=app
+ 3
Actually, my initial answer was wrong, so I deleted it. I don't know why this is happening.
How did you find this?
+ 3
Not much into python so Iam not sure about it. But I found from below links related. It only Immutable at single level. Any alias reference, will change mutation..
https://stackoverflow.com/questions/41795116/difference-between-mappingproxytype-and-pep-416-frozendict
https://adamj.eu/tech/2022/01/05/how-to-make-immutable-dict-in-python/
+ 3
Lisa I haven't tried it, but I assume that you can use all (or at least almost all) magic methods in a weird and counterintuitive way. The equality operator has one important distinction though. As far as I know you can use it with any two types of objects. Other magic methods like __gt__() (greater than or ">") require both arguments to be of the same type.
So e.g. In my variant 2 you can replace __eq__() with __gt__() without problem because both objects have the same type. In the other examples you can't because the objects have different types.
+ 3
+ 2
After thinking about this some more I think the answer is that thanks to the magic method you can use "==" for whatever function you want as long as it has two parameters. And that function can include value assignment.
But I definitely would not recommend doing it unless you want to *really* annoy whoever has to maintain the code.
+ 2
Another illustration:
https://code.sololearn.com/ch9ObO0FpXYM/?ref=app
+ 2
Simon Sauter MappingProxyType is immutable. Makes things a bit more weird.
+ 2
Simon Sauter thanks.
I tried it with the example codes and it only appears for ==, e.g. not for neq? Following the explanations in this thread, it happens for the MappingProxyType because it already overloads ==. Do I understand it correctly?
+ 2
Lisa here's an example using __neg__() to assign a value (actually instead of assigning a different number you could just as well assign an object of a completely different type):
https://code.sololearn.com/cVEzKJXe7wsC/?ref=app
+ 2
I wouldn't call it a bug and think the decision to reject the bug report was correct.
The fact that the underlying dictionary can be changed is intended and mentioned in the documentation.
The fact that the underlying dictionary is sent to functions is necessary. And as people pointed out in the bug report discussion doing so in a safe(r) way would be difficult and kind of overkill.
I don't know if there is a necessity for allowing to (ab)use __eq__() in the way done here. But since this is hardly something anyone will do accidentally I don't see a good reason for restricting it. I think this is a case where the python principle that "we are all consenting adults here" should apply.
The fact that these taken together can be used like this is not really a problem, given that this seems to be an "artifical" use that probably will never occur by accident.
+ 1
I'm afraid things are only getting weirder:
https://code.sololearn.com/c5sq3GvO6Mc9/?ref=app
+ 1
There are actually two weird things here.
1. Why does "other" refer to orig instead of proxy?
2. Why does changing orig this way affect proxy?
+ 1
It is specific to the equality operator?
+ 1
The trick here is to use the magic method of one class to change an object of a different class. That's necessary since we don't want to change the definition of the MappingProxyType class. So we need a method that works with objects of two different types. And that is just __eq__().
When you can change the definition of your class at will you can use other magic methods the same way. As I said, in my variant 2 you can use other methods because the objects are of weird_object type.
- 1
Compare to, ==.