Hacker News new | ask | show | jobs
by DreamOther 2118 days ago
Its funny, I enjoy python for different reasons. The import statement and all the "allowing the language to grow" is great, but not what makes me use it over competitors. In fact, I'd argue pip and virtualenv are kind of worse to use than npm, go get, rust crates etc - some might disagree here, but I feel the experience could be a lot better.

Main reasons I love and continue to use python...

1. Python 2/3 break. A breaking update sounds scary, but getting rid of the accumulation of "language warts" all at once was literally amazing. And by all at once, I mean a gradual transition over a decade. I also think Node's way of having individual API's have an independent "stability" metric that is unrelated to the platform or language is another decent way of handling this.

2. They've taken great care with the most common data structures, with regard to both performance and ergonomics. A python dictionary is wonderful to use and is actually quite fast (specialized for common cases and transparently alters hashing algorithms depending on input). You can use any immutable data structure as a key (tuples!). Its so nice.

3. For somewhat complicated work, the standard library actually has all the good stuff baked in. heapq, deque, bisect, permutations, combinations, lru, and the list goes on. Then convenience oriented data structures like Counter, defaultdict and such that other languages would balk at adding. When you have stuff like list and dictionary comprehensions layered on top of these baseline algorithmic tools, it feels so damn good. Do these things have warts? Yes, sometimes. Like heapq is default min heap with no way to change the behavior other than negating the input/output - but I don't care, its there, and its usable and you can explore it to the edges pretty quickly.

The only still-pretty-shitty parts that makes it less than perfect in my eyes is the GIL combined with asyncio/async/await being modal.

This is just a guess, but it seems like languages that over-specify internals paired with a goal of never breaking backwards compatibility are doomed to ... not fail, clearly, but to be a pain in the ass to use forever. Take unordered_map from C++: what an unholy mess made out of the most common data structure in computer science. Yes, you can use Google's swiss table impl in Abseil or some competitor, but the fact that I have an unwieldy poorly designed hash map baked into standard library for all time is such a missed opportunity. std::async was a huge missed opportunity as well (bad default arguments, not guaranteed to be backed by a thread pool).

In short, not allowing for mistakes is a tragedy that creates pressure to over-specify, which I think damages everything in ways you cannot predict.