4 comments

[ 3.1 ms ] story [ 18.4 ms ] thread
This kinda reads as the writer doesn't actually know Python all that well, these definitely aren't Python antipatterns.

Lists and Sets are not the same data structure, obviously Sets are faster for finding if an item exists or not, but Sets are immutable and you can't have duplicate values like in a list. You can't substitue Sets for Lists for everything. What if I'm iterating over a list where I need to keep duplicates?

Also, who wraps a try except over a dictionary? Just use .get(), it defaults to None instead of raising a KeyError and even let's you pass a default value as the 2nd argument, .get("a", "hello").

The most basic google search could have helped with these.

1. I wasn't intending to make it sound like you should substitute all your Lists to Sets as I am well aware of the differences between them. I was trying to convey that on some specific cases Sets are faster than lists, whether if it's obvious or not to everyone, I don't know.

2. Yes, you can use .get(), I was trying to demonstrate the idea of EAFP, and thought that the dictionary snippet might serve as a good example, we probably disagree.

nitpicky: sets aren't immutable. frozensets are.
It is not a bad thing to write about basic concepts, but you should put some more thought into your examples. They seem uninspired and too simple for what you are trying to convey.

Some examples:

The EAFP example in itself is not really well-chosen. A simple if is completely acceptable here, and some people already pointed out that using some_dict.get() is even more straightforward and idiomatic. I know it is just an example, but in that case your example needs to be a bit more complex to get the point across. An easy way to show the point would be to e.g. guard multiple dictionary accesses (or access to nested dictionary) with only one try-except clause instead of one big complex if statement. Make up a story where this unstructured dict is coming from, maybe you are parsing JSON or something with optional keys, be creative!

In fact I would actually consider it to be a well-known newbie trap to try to be "pythonic" at all cost and forget that basic control flow constructs exist. Not every explicit check needs to be replaced by Exception handling, not every for-loop needs to be a list-expression, not every list needs to be lazily created using a generator function, etc.

Another example: You warn against catching too general exceptions, in the worst case by using except with no Exception type given, without explaining why this would be a problem (e.g. because you would then catch KeyboardInterrupt and similar internal exceptions as well).

But then you proceed to advise to catch the general Exception in normal application code, which is only slightly better. These general exception clauses are terrible to refactor later, as nobody can be sure whether you just put in the catch-all clause "just in case", or whether your code actually needs to catch additional exceptions, and in the worst case maybe just didn't feel like looking up the possible exceptions which could be thrown.

Catching a general Exception may be acceptable when mostly writing callbacks in an async framework, where you can actually reasonably fail on an unexpected Exception without your whole program breaking apart, but not everybody is writing an interactive asynchronous program.

And then there are some minor contradictions which just seem sloppy: You drive home the point that inclusions in sets can be checked in O(1) (fast!) while inclusion in lists can be checked in O(n) (slow!) which is fine and dandy. But then in your EAFP example you consider the driving motivation for EAFP that "foo" in some_dict would be too expensive. You even pointed out that a set is essentially already a hash-map/dict. You just said before that hash-table lookup is a fast constant time operation, and now you posit that introducing exception handling is faster?

Also I would like to ask the question whether these tiny "optimizations" are actually worth it, especially if those make the code harder to read.

To summarize: This is a pretty short and basic blog post, and the points are at their core all valid. But by taking uninspired examples which don't really match what you are trying to convey, you still you managed to put guidance in every example, which can be considered highly situational, misleading or even wrong. Giving situational advice is not a bad thing either, but then you should point out when the advice is applicable and especially when it is not.