A practical usage of ChainMap in Python
blog.florimondmanca.com
A practical usage of ChainMap in Python
1–10 of 16 posts
Re: A practical usage of ChainMap in Python
#2 >>> from collections import ChainMap
>>> inv = ChainMap({'Monopoly': 20, 'Nintendo': 200}, {'iMac': 1000, 'Chromebook': 800, 'PC': 400}, {'Jeans': 40, 'T-Shirt': 10})
>>> inv['iMac'] = 9001
>>> inv
ChainMap({'Monopoly': 20, 'Nintendo': 200, 'iMac': 9001}, {'iMac': 1000, 'PC': 400, 'Chromebook': 800}, {'T-Shirt': 10, 'Jeans': 40})
This strikes me very much as the wrong default behaviour. If you want the (IMO expected) behaviour of updating maps later in the list, the docs advocate creating a entirely new class with overridden set and delete methods[0]. That's not the end of the world, but if they had made this the default behaviour then the getting the current behaviour would just be chain_map.maps[0][key] = value
and you wouldn't need to create a new class at all.Does anyone know why this decision was made?
[0]: https://docs.python.org/3.7/library/collections.html#chainma...
Re: A practical usage of ChainMap in Python
#3>>> from collections import ChainMap >>> inv = ChainMap({'Monopoly': 20, 'Nintendo': 200}, {'iMac': 1000, 'Chromebook': 800, 'PC': 400}, {'Jeans': 40, 'T-Shirt': 10}) >>> inv['iMac'] = 9001 >>> inv ChainMap({'Monopoly': 20, 'Nintendo': 200, 'iMac': 9001}, {'iMac': 1000, 'PC': 400, 'Chromebook': 800}, {'T-Shirt': 10, 'Jeans': 40}) This strikes me very much as the wrong default behaviour. If you want the (IMO expected)…
However, it appears that the “locals, globals, builtins” lookup was the design constraint this was intended for, and the core of Python seems to prefer new classes over compact functionality. For example look at OrderedDict not just being an “ordered=“ keyword only parameter (ordered) on dict.
Re: A practical usage of ChainMap in Python
#4[1] https://docs.python.org/3.7/library/collections.html#collect...
Re: A practical usage of ChainMap in Python
#5>>> from collections import ChainMap >>> inv = ChainMap({'Monopoly': 20, 'Nintendo': 200}, {'iMac': 1000, 'Chromebook': 800, 'PC': 400}, {'Jeans': 40, 'T-Shirt': 10}) >>> inv['iMac'] = 9001 >>> inv ChainMap({'Monopoly': 20, 'Nintendo': 200, 'iMac': 9001}, {'iMac': 1000, 'PC': 400, 'Chromebook': 800}, {'T-Shirt': 10, 'Jeans': 40}) This strikes me very much as the wrong default behaviour. If you want the (IMO expected)…
FWIW I find the current behavior preferable. In fact in all cases I use ChainMap the first mapping is always an empty dictionary, because I specifically don't want to mutate the others.
Re: A practical usage of ChainMap in Python
#6>>> from collections import ChainMap >>> inv = ChainMap({'Monopoly': 20, 'Nintendo': 200}, {'iMac': 1000, 'Chromebook': 800, 'PC': 400}, {'Jeans': 40, 'T-Shirt': 10}) >>> inv['iMac'] = 9001 >>> inv ChainMap({'Monopoly': 20, 'Nintendo': 200, 'iMac': 9001}, {'iMac': 1000, 'PC': 400, 'Chromebook': 800}, {'T-Shirt': 10, 'Jeans': 40}) This strikes me very much as the wrong default behaviour. If you want the (IMO expected)…
>>> del inv['IMac']
deleting the key in the first mapping it appears. My guess is it is designed to ensure that updating a key will not update accidentally update a default mapping? This behavior could easily be prevented though by:
>>> from types import MappingProxyType >>> DEFAULTS = MappingProxyType(default_dict) >>> ChainMap(overrides, DEFAULTS)
Re: A practical usage of ChainMap in Python
#7>>> from collections import ChainMap >>> inv = ChainMap({'Monopoly': 20, 'Nintendo': 200}, {'iMac': 1000, 'Chromebook': 800, 'PC': 400}, {'Jeans': 40, 'T-Shirt': 10}) >>> inv['iMac'] = 9001 >>> inv ChainMap({'Monopoly': 20, 'Nintendo': 200, 'iMac': 9001}, {'iMac': 1000, 'PC': 400, 'Chromebook': 800}, {'T-Shirt': 10, 'Jeans': 40}) This strikes me very much as the wrong default behaviour. If you want the (IMO expected)…
Your point is interesting, and it’s how I’ve designed a lot of APIs when I’m not sure how I’ll end up needing the class or function the most: slightly less ergonomic in the know use case, but across the board it has a higher “median” ergonomicity. A third alternative of course would be to add a method to the constructor, specifying this behavior (e.g. write_depth=1). However, it appears that the “locals, globals, bui…
Re: A practical usage of ChainMap in Python
#8I see the example use case is exactly the same as the one given in the python documentation [1]. Any other practical use cases? [1] https://docs.python.org/3.7/library/collections.html#collect...
Re: A practical usage of ChainMap in Python
#9 >>> env.prefix('XDG_')
{'config_dirs': '…', 'current_desktop': '…',
'session_type': 'x11', 'vtnr': '7', …}Re: A practical usage of ChainMap in Python
#10>>> from collections import ChainMap >>> inv = ChainMap({'Monopoly': 20, 'Nintendo': 200}, {'iMac': 1000, 'Chromebook': 800, 'PC': 400}, {'Jeans': 40, 'T-Shirt': 10}) >>> inv['iMac'] = 9001 >>> inv ChainMap({'Monopoly': 20, 'Nintendo': 200, 'iMac': 9001}, {'iMac': 1000, 'PC': 400, 'Chromebook': 800}, {'T-Shirt': 10, 'Jeans': 40}) This strikes me very much as the wrong default behaviour. If you want the (IMO expected)…
chain_map.maps[0][key] = value
I wouldn't expect this to work because `0` is a valid key. It's not safe to assume that an integer lookup is an index.