Particularly, the answer by StackOverflow user `Aaron Hall` upvoted around 680 times [1], also deconstructs and provides eerily similar content as what this post gives (for example, the poorness of the
dict(x, **y)
solution and some performance comparisons).I guess this post does mention itertools.chain and ChainMap ... though I would almost never recommend using those if your goal is to merge two regular dicts. Probably anyone reading the code is going to be baffled unless there was a special reason why generators or ChainMap were needed -- these really don't belong in the discussion; they're very different.
As someone who has used Python almost daily for the past 8 years, I also can't help but feel let down when I read more stuff about being so-called "pythonic." I especially hate it when I see discouraging criticisms on Stack Overflow that seem to scare away newcomers because they didn't know you could do a dict comprehension or something. The whole "pythonic" thing is waaayyyy overrated. Just write code that is clean, and if you use a couple of extra lines, or you loop over a range instead of a for-statement treating something as an Iterator, so what, it really, really doesn't matter in most cases, and you can always profile and fix the few cases where it does. It certainly doesn't matter because of some subjective debates about what is more "readable", like whether a dict-comprehension is "less readable" than a two-line copy-and-update approach.
The python-ideas thread from last year about using + on dictionaries was also an inspiration. I don't recommend reading it in full (there's some painful debating) but there were some really interesting concerns brought up on there in regards to this particular problem.
In regards to newcomers being scared away by criticism on Stack Overflow: I completely sympathize with this point of view. New Python programmers and new programmers especially should not worry about what is "pythonic" until they've become comfortable with their own Python programming abilities. Working and readable code is most important, idiomatic code is simply icing on the cake.
I do however value discussions of what is "pythonic". I often discuss "pythonic" in my classes to instill the idea that community norms change from language to language and even between frameworks and projects.
I really hope the wording of this post didn't come off as elitist. If so, I will certainly need to reconsider my wording for the next one.
I think "pythonic" is a slippery slope. Many people take it too far and begin to develop militant ideas of what "readability" means, or they do silly things. For instance, I once heard a tale about someone needing to create their own toolkit for handling paths in a certain project. It was just going to a wrapper around the usual os.path tools, but would factor out a lot of the team's repetitive code.
That person actually implemented __abs__ so that "abs(p)" resulted in the absolute path for the path object p. Ugh!
The justification was that this is supposed to be more "pythonic" than just writing a simple helper function. And of course, if you say that the documentation about Python idioms or accepted understandings of what is "pythonic" don't have anything to do with the choice to implement something as a special method, the other person's response is just "yes it does" -- their interpretation is that this is what pythonic means. It's like having an interpretation debate about the Bible or something. It means something different to everyone, which makes it pretty useless as a centralized standard.
If you apply good Haskell style, or good C style, or good Java style, to writing Python, your code will be absolutely fine and perfectly readable even in large enterprise codebases (perhaps more so depending on who else reads it).
I think Google's C++ guide has the right idea. You should follow the local conventions of the piece of code you're editing.
If you're working in a Python module where someone puts every function argument on a new line (even if you're not near the 80 char limit) like this
def foo(arg1,
arg2,
...):
# ...
then you should just also do that, and not waste time about whether this is more Pythonic def foo(arg1, arg2,
arg3, ...):
I think if the Python community trumps up this idea of pythonic, it just alienates other people whose natural style (or the guides to their own main languages) tell them differently.Over time, Python developers will learn when it's better to use map than a comprehension, how to style things, how avoid doing needlessly complicated things like the __abs__ example above. You don't have to drill "pythonic" stuff into them for that sort of clean code common sense to emerge, and you certainly don't need to make it a major point of community pride or identity.
* Javascript (ECMAScript4, ECMAScript5 and ECMAScript6 all have different ways of iterating a collection! Not the mention the many utility libraries which implement quite basic things in different ways)
* PHP (Old school no-OO built-ins, <?php templating vs Java style OO PHP5+ and the SPL, )
* C++ ("C with classes" vs varying degrees of template magic, STL and Boost)
I'm beginning to feel quite sceptical about whether these types of changes are actually worth it. % on strings was a little bit quirky but fine - I don't see why .format() is better -- people are still going to encounter the first so the damage is already done. Using either of the first two with .update() was fine.
>>> x = {'a': {}}
>>> y = x.copy()
>>> y['a']['b'] = 'c'
>>> x
{'a': {'b': 'c'}} >>> context = defaults.copy()
>>> context.update(user)