I've just read your PEP 585 draft and have some questions.
When you say
"
Like the merge operator and list concatenation, the difference
operator requires both operands to be dicts, while the augmented
version allows any iterable of keys.
>>> d - {'spam', 'parrot'}
Traceback (most recent call last):
...
TypeError: cannot take the difference of dict and set
>>> d -= {'spam', 'parrot'}
>>> print(d)
{'eggs': 2, 'cheese': 'cheddar'}
>>> d -= [('spam', 999)]
>>> print(d)
{'spam': 999, 'eggs': 2, 'cheese': 'cheddar', 'aardvark': 'Ethel'}
"
The option d -= {'spam', 'parrot'} where parrot does not exist in
the d dict, will raise an exception (eg. KeyNotFound) or be silent?
The option d -= [('spam', 999)] should remove the pair from the
dict, correct? But the print that follows still shows it there. It's
a mistake or am I missing something?
My understanding is that:
- (Q1) Attempting to discard a key not in the target of the augmented assignment would not raise a KeyError (or any Exception for that matter). This is analogous to how the - operator works on sets and is consistent with the pure python implementation towards the bottom of the PEP.
- (Q2) This one got me as well while implementing the proposal in cpython, but there is a difference in what "part" of the RHS the operators "care about" if the RHS isn't a dict. The += operator expects 2-tuples and will treat them as (key, value) pairs. The -= operator doesn't attempt to unpack the RHS's elements as += does and expects keys. So d -= [('spam', 999)] treated the tuple as a key and attempted to discard it.
IOW,
d = {
'spam': 999,
('spam', 999): True
}
d -= [('spam', 999)]
Would discard the key ('spam', 999) and corresponding value True.
Which highlights a possibly surprising incongruence between the operators:
d = {}
update = [(1,1), (2,2), (3,3)]
d += update
d -= update
assert d == {} # will raise, as d still has 3 items
Similarly,
d = {}
update = {1:1, 2:2, 3:3}
d += update.items()
d -= update.items()
assert d == {} # will raise, for the same reason
d -= update.keys()
assert d == {} # would pass without issue
That being said I (personally) wouldn't consider it a deal-breaker and still would very much appreciate of the added functionality (regardless of the choice of operator).
- Jim