
Good points, Antoine! The intent is to mutate the dictionary with no side effects if a key exists — and without the extra code that comes along with a control structure, a try except, or positing a None to throw away. For me, pop() says "give me something." Since the intent is to mutate the dictionary only and not "get something," I'd prefer (i) not to use a function that returns a value and (ii) not to specify a return value None just so that it can be thrown away. Perhaps if pop()'s default return value were None—as it is with, say, get()—I would use pop() as you describe. But pop() doesn't have a default value unless you give it one, and pop() always returns a value. Where does this land with PEP 20? I think the use of pop() as you suggest lands on the implicit side of things and is not as readable: the reader has to ask, "what are we doing with the default value? Oh. Nothing. It's to delete a dict entry." However, pop() with the default value of None is practical, and practicality does beat purity. I agree that operator overloading needs to be consistent and easy to understand, and in that regard -= with the dict key probably does not withstand the PEP 20 tests. Furthermore, in support of your point, the language has moved in the direction of set operations between dicts using operators: for example, + for union of dicts. To satisfy set- and key-based operations, one could overload the augmented arithmetic assignment operators so that -= with a string would delete the entry with a matching key, while -= with a dict would delete the entry with a matching key and value. Again, that may be too recherché or hard-to-explain (cf PEP 20). Perhaps, then, it would be best to leave dict alone and just overload operators in subclasses for specific uses!