Don’t know why python gets so much love. It’s a painful language as soon as more than one person is involved. What the author describes is just the tip of the iceberg
The same reason people are not flocking to the Lisps of the world: mathematical rigour and precision does not translate to higher legibility and understandability.
Python's list /dict/set comprehensions are equivalent to typed for loops: where everyone complains about Python being lax with types, it's weird that one statement that guarantees a return type is now the target.
Yet most other languages don't have the "properly ordered" for loop, Rust included (it's not "from iter as var" there either).
It's even funnier when function calling in one language is compared to syntax in another (you can do function calling for everything in most languages, a la Lisp). Esp in the given example for Python: there is functools.map, after all.
"the target"? The OP complaint is not that the statement exists, but that the output expression comes before the context that establishes its meaning. This is not just a problem for autocomplete, but people often report difficulties understanding complex comprehensions.
As for comprehensions themselves, ignoring that problem I find them a powerful and concise way to express a collection of computed values when that's possible. And I'm particularly fond of generator expressions (which you didn't mention) ... they often avoid unnecessary auxiliary memory, and cannot be replaced with an inline for loop--only with a generator function with a yield statement.
BTW, I don't understand your comment about types. What's the type of (x for x in foo()) ?
> Yet most other languages don't have the "properly ordered" for loop, Rust included (it's not "from iter as var" there either).
The relative order of the variable being iterated on and the loop variable name is not relevant to OP's complaint. OP only requires that the expression which uses the loop variable comes after both, which is the case in Rust.
This hasn't been my experience, but we use the Google style guide, linters, and static type verification to cut down on the number of options for how to write the program. Python has definitely strayed from its "one right way to do a thing" roots, but in the set of languages I use regularly it gives about the same amount of issues as JavaScript (and far, far less than C++) regarding having to deal with quirks that vary from user to user.
Failure to understand something is not a virtue. That it does get a lot of love strongly suggests that there are reasons for that. Of course it has flaws, but that alone doesn't tell us anything; only comparisons do. Create a comprehensive pro/con list and see how it fares. Then compare that to pro/con lists for other languages.
> That it does get a lot of love strongly suggests that there are reasons for that.
Reasons, sure, but whether those reasons correlate with things that matter is a different question altogether.
Python has a really strong on-ramp and, these days, lots of network effects that make it a common default choice, like Java but for individual projects. The rub is that those same properties—ones that make a language or codebase friendly to beginners—also add friction to expert usage and work.
> Failure to understand something is not a virtue.
This is what I want to say to all the Bash-haters that knee-jerk a "you should use a real language like Python" in the comments to every article that shows any Bash at all. It's a pet peeve of mine.
> Of course it has flaws, but that alone doesn't tell us anything; only comparisons do.
Comparisons won't tell us anything. If Python were the only programming language in existence, that doesn't imply that it would be loved. Or, if we could establish that Python is the technically worst programming language to ever be created, that doesn't imply that wouldn't be loved. Look at how many people in the world love other people who are by all reasonable measures bad for them (e.g. abusive). Love isn't rational. It is unlikely that it is possible for us to truly understand.
I used to agree with this completely, but type annotations & checking have made it much more reasonable. I still wouldn't choose it for a large project, but types have made it much, much easier to work with others' python code.
Python with strict type checking and its huge stdlib is my favourite scripting language now.
I agree, it's not too bad if you enable strict Pyright checking in CI, and you use `uv` and you don't care remotely about performance.
That's quite a lot of ifs though. Tbh I haven't found anything significantly better for scripting though. Deno is pretty nice but Typescript really has just as many warts as Python. At least it isn't so dog slow.
I find list and dict comprehensions are a lot less error prone and more robust than the “manual” alternatives.
I would say unless you have a good reason to do so, features such as meta classes or monkey patching would be top of list to avoid in shared codebases.
> For a language where there is supposed to be only one way to do things
That's not what the Zen says, it says that there should be one -- and preferably only one -- obvious way to do it.
That is, for any given task, it is most important that there is at least one obvious way, but also desirable that there should only be one obvious way, to do it. But there are necessarily going to be multiple ways to do most things, because if there was only one way, most of them for non-trivial tasks would be non-obvious.
The goal of Python was never to be the smallest Turing-complete language, and have no redundancy.
If I have to write Python like Go, I'd rather just write Go. (Not disagreeing with you, but this is one of many reasons that Python is the least-favourite language that I use on a regular basis.)
Thankfully, uv makes this a lot better, but it'll still be a while before that percolates to the entire ecosystem, if ever.
There are real concerns about tying the language's future to a VC-backed project, but at the same time, it's just such an improvement on the state of things that I find it hard not to use.
It's the exceptional codebase that's nice to work with when it gets large and has many contributors. Most won't succeed no matter the language. Language is a factor, but I believe a more important factor is caring a lot.
I'm working on a python codebase for 15 years in a row that's nearing 1 million lines of code. Each year with it is better than the last, to the extent that it's painful to write code in a fresh project without all the libraries and dev tools.
Your experience with Python is valid and I've heard it echoed enough times, and I'd believe it in any language, but my experience encourages me to recommend it. The advice I'd give is to care a lot, review code, and keep investing in improvements and dev tools. Git pre commit hooks (just on changed modules) with ruff, pylint, pyright, isort, unit test execution help a lot for keeping quality up and saving time in code review.
I love python, as long as were are talking about small teams, short, and short lived programs. The lack of static types makes things quick to implement even if it isn't too sound, and the strong typing keeps you from fucking up too badly. That is why I think it gets so much love in data science, it is great for noodling around while you are trying to figure something out.
On the other hand if you are going to be building something that is going to be long lived, with multiple different teams supporting it over time, and\or larger programs where it all doesn't fit in (human) memory, well then python is going to bite you in the ass.
There isn't a one size fits all programming language, you need at least two. A "soft" language that stays out of your way and lets you figure things out, and a "hard" language that forces the details to be right for long term stability and support.
Because everything that tries to fix it is just as painful in different ways.
I've had the displeasure of working in codebases using the style of programming op says is great. It's pretty neat. Until you get a chain 40 deep and you have to debug it. You either have to use language features, like show in pyspark, which don't scale when you need to trace a dozen transformations, or you get back to imperative style loops so you can log what's happening where.
Python was established as a fun and sensible language that was usable and batteries-included at a time when everything else was either expensive or excruciating, and has been coasting in that success ever since. If you'd only coded in bash, C/C++, and late-'90s Java, Python was a revelation.
Lists comprehensions were added to the language after it was already established and popular and imho was the first sign that the emperor might be naked.
Python 3 was the death of it, imho, since it showed that improving the language was just too difficult.
It's my 18th language and I prefer it over the alternatives. If I need to write an app I'll use Swift. If I need to do some web work I'll switch to TypeScript. To get work done it's Python all the way.
necovek|6 months ago
Python's list /dict/set comprehensions are equivalent to typed for loops: where everyone complains about Python being lax with types, it's weird that one statement that guarantees a return type is now the target.
Yet most other languages don't have the "properly ordered" for loop, Rust included (it's not "from iter as var" there either).
It's even funnier when function calling in one language is compared to syntax in another (you can do function calling for everything in most languages, a la Lisp). Esp in the given example for Python: there is functools.map, after all.
jibal|6 months ago
As for comprehensions themselves, ignoring that problem I find them a powerful and concise way to express a collection of computed values when that's possible. And I'm particularly fond of generator expressions (which you didn't mention) ... they often avoid unnecessary auxiliary memory, and cannot be replaced with an inline for loop--only with a generator function with a yield statement.
BTW, I don't understand your comment about types. What's the type of (x for x in foo()) ?
ChadNauseam|6 months ago
The relative order of the variable being iterated on and the loop variable name is not relevant to OP's complaint. OP only requires that the expression which uses the loop variable comes after both, which is the case in Rust.
shadowgovt|6 months ago
jibal|6 months ago
xelxebar|6 months ago
Reasons, sure, but whether those reasons correlate with things that matter is a different question altogether.
Python has a really strong on-ramp and, these days, lots of network effects that make it a common default choice, like Java but for individual projects. The rub is that those same properties—ones that make a language or codebase friendly to beginners—also add friction to expert usage and work.
> Failure to understand something is not a virtue.
This is what I want to say to all the Bash-haters that knee-jerk a "you should use a real language like Python" in the comments to every article that shows any Bash at all. It's a pet peeve of mine.
9rx|6 months ago
Comparisons won't tell us anything. If Python were the only programming language in existence, that doesn't imply that it would be loved. Or, if we could establish that Python is the technically worst programming language to ever be created, that doesn't imply that wouldn't be loved. Look at how many people in the world love other people who are by all reasonable measures bad for them (e.g. abusive). Love isn't rational. It is unlikely that it is possible for us to truly understand.
unknown|6 months ago
[deleted]
mb7733|6 months ago
Python with strict type checking and its huge stdlib is my favourite scripting language now.
IshKebab|6 months ago
That's quite a lot of ifs though. Tbh I haven't found anything significantly better for scripting though. Deno is pretty nice but Typescript really has just as many warts as Python. At least it isn't so dog slow.
instig007|6 months ago
It's time to try Scala 3 with Java libs' inbound interop: https://docs.scala-lang.org/scala3/book/scala-features.html
williamscales|6 months ago
For a language where there is supposed to be only one way to do things, there are an awful lot of ways to do things.
Don’t get me wrong, writing a list comprehension can be very satisfying and golf-y But if there should be one way to do things, they do not belong.
ipython|6 months ago
I would say unless you have a good reason to do so, features such as meta classes or monkey patching would be top of list to avoid in shared codebases.
dragonwriter|6 months ago
That's not what the Zen says, it says that there should be one -- and preferably only one -- obvious way to do it.
That is, for any given task, it is most important that there is at least one obvious way, but also desirable that there should only be one obvious way, to do it. But there are necessarily going to be multiple ways to do most things, because if there was only one way, most of them for non-trivial tasks would be non-obvious.
The goal of Python was never to be the smallest Turing-complete language, and have no redundancy.
Philpax|6 months ago
SkepticalWhale|6 months ago
Philpax|6 months ago
There are real concerns about tying the language's future to a VC-backed project, but at the same time, it's just such an improvement on the state of things that I find it hard not to use.
smilliken|6 months ago
I'm working on a python codebase for 15 years in a row that's nearing 1 million lines of code. Each year with it is better than the last, to the extent that it's painful to write code in a fresh project without all the libraries and dev tools.
Your experience with Python is valid and I've heard it echoed enough times, and I'd believe it in any language, but my experience encourages me to recommend it. The advice I'd give is to care a lot, review code, and keep investing in improvements and dev tools. Git pre commit hooks (just on changed modules) with ruff, pylint, pyright, isort, unit test execution help a lot for keeping quality up and saving time in code review.
stonemetal12|6 months ago
On the other hand if you are going to be building something that is going to be long lived, with multiple different teams supporting it over time, and\or larger programs where it all doesn't fit in (human) memory, well then python is going to bite you in the ass.
There isn't a one size fits all programming language, you need at least two. A "soft" language that stays out of your way and lets you figure things out, and a "hard" language that forces the details to be right for long term stability and support.
jbs789|6 months ago
noosphr|6 months ago
I've had the displeasure of working in codebases using the style of programming op says is great. It's pretty neat. Until you get a chain 40 deep and you have to debug it. You either have to use language features, like show in pyspark, which don't scale when you need to trace a dozen transformations, or you get back to imperative style loops so you can log what's happening where.
rjbwork|6 months ago
jimbokun|6 months ago
mrheosuper|6 months ago
dragonwriter|6 months ago
Pxtl|6 months ago
Lists comprehensions were added to the language after it was already established and popular and imho was the first sign that the emperor might be naked.
Python 3 was the death of it, imho, since it showed that improving the language was just too difficult.
ivanjermakov|6 months ago
doug_durham|6 months ago
xigoi|6 months ago
hnlmorg|6 months ago
People complain that we can’t have nice things. But even when we do, enough developers will be lazy enough not to learn them anyway.