You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Document dict behavior when setting equal but not identical key #91081
As @methane also said on the PR, this is a backward compatibility break and we can't just change the behavior. I'd be opposed to a change here: the proposed behavior isn't clearly better than the existing behavior (sometimes you want one behavior, sometimes another), and it will be difficult to find and adjust code that relies on the existing behavior.
How about if we make PR instead to the documentation about this behaviour?
I think this behaviour is a little surprising (you need to know the internals of how WeakKeyDict keys are constructed and checked) and while I understand you do not want breaking change, maybe this should be explained to the users and example given how to apply the workaround?
changed the title [-]Replace key if not identical to old key in dict[/-][+]Document dict behavior when setting equal but not identical key[/+]on Mar 5, 2022
"""
This class is intended primarily for use with key objects whose equals methods test for object identity using the == operator. Once such a key is discarded it can never be recreated, so it is impossible to do a lookup of that key in a WeakHashMap at some later time and be surprised that its entry has been removed. This class will work perfectly well with key objects whose equals methods are not based upon object identity, such as String instances. With such recreatable key objects, however, the automatic removal of WeakHashMap entries whose keys have been discarded may prove to be confusing.
"""
Thanks to slateny, the behaviour is now documented in the weakref docs. Since this addresses OP's issue, which is where this is most clearly pernicious, I'm closing. But do let me know if you think this should be documented more generally somewhere else.
Activity
malthe commentedon Mar 4, 2022
When a key that is equal to an existing key (but not the same object identity) is used to set a new value, the key itself is not replaced.
This manifests perhaps most clearly in
weakref.WeakKeyDictionarywhere keys can mysteriously disappear.Consider two equal keys, k1 and k2:
We would expect the dictionary to have a single entry k2 => 2. But in fact it is empty now.
JelleZijlstra commentedon Mar 5, 2022
As @methane also said on the PR, this is a backward compatibility break and we can't just change the behavior. I'd be opposed to a change here: the proposed behavior isn't clearly better than the existing behavior (sometimes you want one behavior, sometimes another), and it will be difficult to find and adjust code that relies on the existing behavior.
rhettinger commentedon Mar 5, 2022
I concur with Jelle and Methane that we can't do this without breaking code.
Also if you don't care about dict order, the work around is easy. Just remove the old key:
potiuk commentedon Mar 5, 2022
How about if we make PR instead to the documentation about this behaviour?
I think this behaviour is a little surprising (you need to know the internals of how WeakKeyDict keys are constructed and checked) and while I understand you do not want breaking change, maybe this should be explained to the users and example given how to apply the workaround?
Just following the "least surprise" principle.
JelleZijlstra commentedon Mar 5, 2022
Agree, I couldn't find a place where this behavior is documented. The second paragraph in https://docs.python.org/3.10/library/stdtypes.html#mapping-types-dict comes close. Reopening as a documentation issue.
10 remaining items
[-]Replace key if not identical to old key in dict[/-][+]Document dict behavior when setting equal but not identical key[/+]rhettinger commentedon Mar 5, 2022
The weakref docs in particular should point out the OP's example and highlight the workaround.
malthe commentedon Mar 6, 2022
Java's HashMap has also the (current) Python behavior. An existing same key is not replaced.
methane commentedon Mar 7, 2022
I don't know much about Java, but Java's WeakHashMap is same to Python's WeakKeyDictionary.
https://docs.oracle.com/javase/9/docs/api/java/util/WeakHashMap.html
"""
This class is intended primarily for use with key objects whose equals methods test for object identity using the == operator. Once such a key is discarded it can never be recreated, so it is impossible to do a lookup of that key in a WeakHashMap at some later time and be surprised that its entry has been removed. This class will work perfectly well with key objects whose equals methods are not based upon object identity, such as String instances. With such recreatable key objects, however, the automatic removal of WeakHashMap entries whose keys have been discarded may prove to be confusing.
"""
potiuk commentedon Mar 7, 2022
Yeah. Sounds like adding docs is indeed needed :)
gh-91081: Add note on WeakKeyDictionary behavior when deleting a repl…
pythongh-91081: Add note on WeakKeyDictionary behavior when deleting …
pythongh-91081: Add note on WeakKeyDictionary behavior when deleting …
gh-91081: Add note on WeakKeyDictionary behavior when deleting a repl…
gh-91081: Add note on WeakKeyDictionary behavior when deleting a repl…
hauntsaninja commentedon Dec 24, 2022
Thanks to slateny, the behaviour is now documented in the weakref docs. Since this addresses OP's issue, which is where this is most clearly pernicious, I'm closing. But do let me know if you think this should be documented more generally somewhere else.
Merged main into regmachine branch (#50)