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
ChainMap should preserve order of underlying mappings #76973
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:
assignee=Noneclosed_at=<Date2018-02-11.09:29:52.688>created_at=<Date2018-02-08.08:46:17.632>labels= ['3.7', '3.8', 'type-bug', 'library']
title='ChainMap should preserve order of underlying mappings'updated_at=<Date2018-02-11.09:29:52.687>user='https://github.com/rhettinger'
Sorry, I was wrong. reversed() is not needed here.
The advantage of this implementation is that it can be faster because of iterating mappings in C code instead of Python code. But the side effect of it is that the iterator keeps references to all values. If this is not desirable, the code can be written something like:
On PR 5586 we discussed reverting the order of the iteration by mappings. There are reasons of doing this. But this adds a subtle behavior change. Currently list(ChainMap({1: int}, {1.0: float})) returns [1]. With reversed() it will return [1.0]. This change LGTM.
New changeset 170b3f7 by Raymond Hettinger (Miss Islington (bot)) in branch '3.7': bpo-32792: Preserve mapping order in ChainMap() (GH-5586) (#GH-5617) 170b3f7
Activity
rhettinger commentedon Feb 8, 2018
This also applies to 3.6 because ChainMap can be used with OrderedDict.
serhiy-storchaka commentedon Feb 8, 2018
An alternate implementation:
Unfortunately both implementations work only with hashable keys. In general case mappings may be not hashtables.
ned-deily commentedon Feb 8, 2018
See discussion on PR 5586 regarding backporting to 3.6.x.
serhiy-storchaka commentedon Feb 10, 2018
Sorry, I was wrong. reversed() is not needed here.
The advantage of this implementation is that it can be faster because of iterating mappings in C code instead of Python code. But the side effect of it is that the iterator keeps references to all values. If this is not desirable, the code can be written something like:
rhettinger commentedon Feb 11, 2018
New changeset 3793f95 by Raymond Hettinger in branch 'master':
bpo-32792: Preserve mapping order in ChainMap() (GH-5586)
3793f95
serhiy-storchaka commentedon Feb 11, 2018
On PR 5586 we discussed reverting the order of the iteration by mappings. There are reasons of doing this. But this adds a subtle behavior change. Currently list(ChainMap({1: int}, {1.0: float})) returns [1]. With reversed() it will return [1.0]. This change LGTM.
serhiy-storchaka commentedon Feb 11, 2018
The code in msg311969 doesn't reuse hash values. The following implementations do this:
or, without keeping reverences to values:
rhettinger commentedon Feb 11, 2018
New changeset 170b3f7 by Raymond Hettinger (Miss Islington (bot)) in branch '3.7':
bpo-32792: Preserve mapping order in ChainMap() (GH-5586) (#GH-5617)
170b3f7
rhettinger commentedon Feb 11, 2018
That doesn't make sense. The dict.update() method reuses the hashes of the input mappings when possible.
>>> from collections import ChainMap >>> class Int(int): def __hash__(self): print(f'Hashing {self}', file=sys.stderr) return int.__hash__(self) >>> import sys >>> d = { Int(1): 'f1', Int(2): 'f2' } Hashing 1 Hashing 2 >>> e = { Int(1): 's1', Int(3): 's3' } Hashing 1 Hashing 3 >>> c = ChainMap(d, e) >>> list(c) # Note, no calls to hash() were made [1, 3, 2]serhiy-storchaka commentedon Feb 11, 2018
I referred to msg311969, not msg311822.