Repository navigation
Document dict behavior when setting equal but not identical key #91081
Description
Activity
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:
d = WeakKeyDictionary() d[k1] = 1 d[k2] = 2 del k1
We would expect the dictionary to have a single entry k2 => 2. But in fact it is empty now.
- addedstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Mar 4, 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.
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:
d.pop(k); d[k] = vHow 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.
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.
- added3.9 (EOL)end of lifeend of life3.10 (EOL)end of lifeend of life3.11only security fixesonly security fixesdocsDocumentation in the Doc dirDocumentation in the Doc dir
on Mar 5, 2022 10 remaining items
- 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 The weakref docs in particular should point out the OP's example and highlight the workaround.
Java's HashMap has also the (current) Python behavior. An existing same key is not replaced.
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.
"""Yeah. Sounds like adding docs is indeed needed :)
- added a commit that references this issue
on Dec 21, 2022 - added 4 commits that reference this issue
on Dec 21, 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.
- added a commit that references this issue
on Dec 28, 2022
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
Linked PRs