Hence there is nothing hard or mysterious what the + operator should do. People are nit picking on this.
Sorry, I honestly don't understand what's the meaning of that (I know a little bit of Python, C/C++, ASP.Net, etc...).
Concerning adding dicts: thinking over it I am more or less neutral as I think that somebody that would dare doing it would feel the pressure of reading the docs to know what the operator would do (e.g. merge distinct keys & overwrite-left/concatenate/ignore-right values of duplicate keys?).
On the other hand in Python I keep trying from time to time to e.g. cast "integer"s into "bytes" using "bytes(my_integer)", which results in a "my_integer"-bytes variable initialized to zeroes (ha-ha), so whatever would be implemented to add dicts using an op might be good for a large part of users but at the same time bad for the other part (that are inexperienced, have a different ways of thinking, etc...) => this might in turn weaken the language's acceptance.
{ * * d1, * * d2} -- unpack the two dicts and feed them both as input to dict comprehension to construct a new dict.
d1.update(d2) does the same merge strategy, but modifying d1 in-place.
Sure, there's five different ways to go about handling collisions, but there's already a well-defined, commonly used methodology, so it's fair to implement syntax sugar for it. It's also not too difficult to understand, and easy to look up (particularly compared to {* * d1,* * d2}).
And I'm not actually aware of any other merge strategy being included in the python stdlib, which implies that this strategy being the best useful default, has been decided long before this operator came into question.
My point: don’t just pick words, explain why those words were chosen.
If Penny is a class, then maybe you're asking what happens when you combine two arrays (or Python lists) of Penny objects? You get one array (list) containing all the Penny objects.
Perhaps you're getting at something like what if you have two "wallet" dictionaries you want to merge?
Let's say each wallet dict has a list of Penny objects, Dime objects, $5 notes, etc. If you are merging the wallets, maybe you don't want to overwrite the first wallet's Penny list with the second wallet's Penny list and instead you want to combine them.
This is where a dictionary comprehension can come in handy. Just iterate on the second wallet's items and add each item's value to the first wallet's corresponding value at the same key to create a new wallet object (or update one of your two existing wallets by setting the wallet equal to the comprehesion). You would have to add additional logic if you had any nested dictionaries in your wallet dictionary or another type that doesn't combine with the + operator, such as sets.
The other case is something like when your wallet gets sent off to the thief api. To make this more Pythonic, let's say you have a cached idea of your wallet's contents before your wallet itself is sent over the api. Once your actual wallet comes back and you pull it out to pay for something and realize it's empty, you merge the wallet you're holding with the cached idea of the wallet in your head, effectively updating the wallet to empty. If the key values are still on your returned wallet's dict, just now they're a bunch of empty lists as values, this will work fine:
cached_wallet.update(my_wallet)
However, if the key value sets are removed entirely from the wallet returned by the thief api, you'd probably be better off doing: cached_wallet = my_wallet
This is because in Python the first example would have no affect on your cached idea of the wallet because an empty dict passed to the update method will not modify the dict you're attempting to update. So actually the second approach is much more robust here, unless of course it's problematic for some other part of your system to have a keyless wallet floating around (although I'd suggest fixing those other parts of your system by having defaults in place).You could also use a dictionary comprehension in this case, making use of the get method with defaults while iterating on the emptied wallet you're holding like this maybe:
cached_wallet.update({
k: my_wallet.get(k, type(v)()) for k, v in cached_wallet.items()
})
If the thief put a new key value pair in your wallet, you wouldn't get it in the above comprehension, so you might want to do this in some cases: cached_wallet.update(
**{ k: my_wallet.get(k, type(v)()) for k, v in cached_wallet.items() },
**my_wallet,
)
Although that may be called out as more expensive/redundant than necessary, you may want to combine the .keys() from both dictionaries, cast them as a set to dedupe then iterate through the actual wallet on those and fuck all, you're tossing the dirty tissue he stuffed into your wallet in the garbage anyway ... but then actually you decide to keep it, there may be DNA evidence here ... you have no idea how you're going to actually parse and apply this evidence and it's kinda disgusting and, ugh, get a hold of yourself, toss that out and go wash your hands and then focus on making sure the credit cards that are missing are canceled and hope to God that updating your card number on your Fubo TV streaming account doesn't invalidate your legacy subscription that lets you watch the Barcelona game each weekend for $10/mo because there's no way in hell you're going to start paying them $40/mo, that's bullshit. Python 3.7.2 (default, Dec 30 2018, 08:55:50)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 'foo' + 'bar' == 'bar' + 'foo'
False
>>> ['foo'] + ['bar'] == ['bar'] + ['foo']
False1) I either want them to be overridden or not. The current .update can do both, you just put the dict you don't want to override as its argument
2) finding common keys is a different problem, which can be solved in a different way
So no, throwing an exception is just completely useless and won't make any of the common cases easier