Lance Ellinghouse:
why can't I add dictionaries like I can other objects?
...
if a and b both had the same keys, then I think b should override
the keys in a.
In my own early Python code, I sometimes used + when I wanted an update semantic, so I can confirm that your expectations aren't universal.
And that's what this comes down to - is bool(time(0, 0))==False the generally expected behavior (which is a higher threshold than reasonable behavior)? What are the likely errors? Do the advantages outweigh the disadvantages?
That's why an argument about the zero element is only somewhat relevant - most programmers aren't mathematicians, and practicality beats purity.
>>> a = Counter()
>>> a[1] = a
>>> b = Counter()
>>> b[1] = b
>>> a + b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "...../collections.py", line 536, in __add__
newcount = self[elem] + other[elem]
File "...../collections.py", line 534, in __add__
result = Counter()
RuntimeError: maximum recursion depth exceeded
If dict() implemented add as you propose then it would be subject to the same errors. This observation doesn't make your proposal wrong. I mean it to point out the subtle complexities which might come up if a large number of people don't know what it's supposed (and even documented) to do.
That's an interesting point, but I'm inclined to say that very few languages could come up with {1:this} - Prolog could, I think - and that running into those errors in Python would be user error.
That said, this is a good example of the expressivity of this, which mathematical definitions often implicitly disallow.
An analysis shouldn't stop at "user error". Instead, ask if the programming language design plays a role.
For example, NUL terminated strings lead to a lot of user errors, some of which lead to security holes. Other string representations don't have that flaw, though come with a different cost concern. Is a buffer overflow "user error"? Some would say it is. But the language design makes those errors more dangerous.
Or in Python, there's no technical reason to have a ":" at the end of the line before an indented block. Instead, it's there because user studies show that people learning ABC (which influenced a lot of early Python) made fewer mistakes if the ":" was present than if it wasn't.
Are indentation mistakes user error? Certainly users play a role. But again, the design does as well.
So saying that something is a "user error" with no further analysis absolves the designer of any responsibility, and I disagree with that idea.
There are at least 4 different ways to handle dict+dict in Python. At least three have come up in this thread as the proposed correct solution. Even if there is a mathematically clean solution, if only 10% of the people expect it to work that way, then why should Python introduce something which is so error prone? No support for dict+dict is 100% error prone, of course, but trivially identified in testing. While Counter+Counter-like behavior has subtle consequences that will trip people up.
(As another example of the subtleties, consider an inverted index mapping word to a list of document ids:
This is wrong because the += changes merged_collection["the"], which is the same list as collection_a["the"]. So even though it looks like good code, and it is good code for any value where x+=y is the same as x=x+y, it may cause problems which are hard to spot.)
"In the face of ambiguity, resist the temptation to guess."
That's how it usually works with functions.