[Python-ideas] PEP: Dict addition and subtraction

James Lu jamtlu at gmail.com
Sun Mar 3 21:28:30 EST 2019


I propose that the + sign merge two python dictionaries such that if there are conflicting keys, a KeyError is thrown. 

This way, d1 + d2 isn’t just another obvious way to do {**d1, **d2}. The second syntax makes it clear that a new dictionary is being constructed and that d2 overrides keys from d1.

One can reasonably expect or imagine a situation where a section of code that expects to merge two dictionaries with non-conflicting keys commits a semantic error if it merges two dictionaries with conflicting keys.

To better explain, imagine a program where options is a global variable storing parsed values from the command line.

def verbose_options():
 if options.quiet
     return {'verbose': True}

def quiet_options():
 if options.quiet:
     return {'verbose': False}

If we were to define an options() function, return {**quiet_options(), **verbose_options()} implies that verbose overrules quiet; whereas return quiet_options() + verbose_options() implies that verbose and quiet cannot be used simultaneously. I am not aware of another easy way in Python to merge dictionaries while checking for non-conflicting keys.

Compare:

def settings():
 return {**quiet_options(), **verbose_options()}

def settings():
 try:
     return quiet_options() + verbose_options() 
 except KeyError:
     print('conflicting options used', sys.stderr')
     sys.exit(1)

***

This is a simple scenario, but you can imagine more complex ones as well. Does —quiet-stage-1 loosen —verbose? Does —quiet-stage-1 conflict with —verbose-stage-1?Does —verbosity=5 override —verbosity=4 or cause an error?

Having {**, **} and + do different things provides a convenient and Pythonic way to model such relationships in code. Indeed, you can even combine the two syntaxes in the same expression to show a mix of overriding and exclusionary behavior.

Anyways, I think it’s a good idea to have this semantic difference in behavior so Python developers have a good way to communicate what is expected of the two dictionaries being merged inside the language. This is like an assertion without 

Again, I propose that the + sign merge two python dictionaries such that if there are conflicting keys, a KeyError is thrown, because such “non-conflicting merge” behavior would be useful in Python. It gives clarifying power to the + sign. The + and the {**, **} should serve different roles. 

In other words, explicit + is better than implicit {**, **#, unless explicitly suppressed.  Here + is explicit whereas {**, **} is implicitly allowing inclusive keys, and the KeyError is expressed suppressed by virtue of not using the {**, **} syntax. People expect the + operator to be commutative, while the {**, **} syntax prompts further examination by virtue of its “weird” syntax.


More information about the Python-ideas mailing list