A lot of Python design decisions have felt weird and off to me but they’ve long justified it by saying that it’s those little ugly design choices that make the language so usable and effective in practice compared to more well-designed languages that hardly anybody uses. I’m not enough of an expert to clearly say if that’s really true, but imo, there’s a repeated pattern of slightly weirdly designed languages becoming super popular: Python, Javascript, perhaps C as well. Or, maybe we only notice the weirdness because these languages are used so much and get nitpicked to no end.
Python is awful. There are so many one offs in libraries, none agree on a style, it’s slow, and it’s way too easy to do the wrong thing. I often work with data scientists and have to productionize their jupyter notebooks which is pure suboptimal hell. I guess it must be a good easy learning curve for research/scratchpad
I’ll never not be bitter than Python “won” the scripting language war over Ruby, more or less just because someone did a bit of AI work in it first and it took over that space by default.
Ruby has such a nice holistic consistency to it. With a few exceptions, it feels like it was conceived of by one person with a core idea in mind. Python feels like a mess.
Python is a language for "consenting adults". It doesn't try to prevent you from doing awful things so you can do great things. People who can't program well are given plenty of rope to hang themselves. It shares that with Perl and Ruby.
That said, I find it the nicest, cleanest option of the three. I still wouldn't use it for large and complex projects. I really like it for stuff where one might otherwise use shellscript. It's way way better than shellscript... except if it's all about files and running external commands.
You don’t like working with data scientists. The data science Python ecosystem is really a separate beast that’ll have “normal” coders scratching their heads at the best of times, some of the most popular packages do all sorts of metaprogramming, and the standards for code quality are very different. Don’t blame the language. Well, blame it only in that it allows such things in the first place, which does have some very nice precipitations now and again, as well as some very bad ones.
In an age where people are still standing by C over memory-safe systems programming languages, I feel quite comfortable depending Python for the great many things that Python is good at.
I used to build quant investment notebooks that had to be deployed in production. Lots of problems with that. Mine were: Notebook cells run out of order, so you often have something that works in a session, but not in a fresh run. Developing against limited datasets, so you fail against things you didn’t know to test for. Small adaptions that have to be made every time the notebook is translated into a code file.
We streamlined it by making a graph-structured Computation a first class object that tracked staleness as code or data was updated. Then that class could be directly published, and when failures happened in production, the graph could be serialized with the inputs and intermediate calculation data that caused failure, for investigation in a notebook.
How is that a language problem? Data scientists are not engineers. No matter what language you give them, they will hand you something you are going to have to polish for production.
The fact that Python has become the language of choice for machine learning and data science is not a language issue.
The performance hell thing is also also kind of a virtue, though. The language is awful, so everything that does any amount of compute is FFI'd into third party libraries (numpy, torch, sympy, etc). Those libraries are for the most part pretty well designed... or, at least, keep you in a few pretty well-constrained patterns that are easy enough to translate.
If you've ever read through FORTRAN code from a mathematics department or MATLAB/C/C++ from (non-software) engineering disciplines, then you probably understand why productionizing a jupyter notebook is definitely not the worst of all possible worlds.
I've never become a fan of the language syntax, but otherwise I've become quite smitten with the total Python ecosystem. The Agents/LLMs + uv combo have made Python so useful and productive for me.
My CLI tools publish from Github to PyPI so that I can run tools with just `uvx sql-agent-cli` or `uvx dlna-here. Nothing for me to handle downloading (directly myself), no environment to manually setup, portable (Linux, Windows, Mac, ARM, x86). Easy for agents to run from a skill.md file without any other prereq than uv.
Really useful library ecosystem to leverage. No more shell scripts, or TS/JS/PHP backend services. I've even used Python on devices I've built around Raspberry Pi Zero 2 boards.
> I often work with data scientists and have to productionize their jupyter notebooks
I'm not a huge Python fan, despite working with it fulltime, but this feels like mixing correlation and causation. Data scientists would not be writing good, optimized code in any language.
Python is amazing compared to writing bat/sh scripts. Different languages are for different purposes, using eg. Rust to write system scripts would just be mental. Whether people abuse those languages for purposes they were not intended for is another story, but that doesn't mean the language is inherently bad. And I mean,
> and it’s way too easy to do the wrong thing
is there another programming language where you believe a data scientist is going to have an easier time writing correct code than Python? Do you think C or Rust or JavaScript or C# make it harder to do the wrong thing?
C'mon man, I don't know any mid and above python developer who seriously has ever considered programming in Jupiter Notebooks. Python is not slow, it's you being the issue. If you are an amateur then it's easy to do the wrong thing, that's true.
The __debug__ constant is really weird - any block of code guarded with `if __debug__:` will be entirely omitted from the bytecode under PYTHONOPTIMIZE=1. This and `assert` are the only two examples of real “conditional compilation” in Python. This is also the reason why you cannot assign to __debug__: doing so would make it possible to invalidate the compiler’s assumption about `if __debug__:` statements.
If 0. Etc. are also compiled out, at compile time __debug__ is simply False or True and the existing optimization paths take care of it.
Assigning to __debug__ wouldn't do anything to the compiler as it never actually reads the variable, so assignment would just cause weirdness from other use
I honestly have never even heard of this constant and I feel like I've been using python for a pretty long time. Although maybe my memory for some things just gets garbage collected if I don't use it enough. Does it actually get used that often in real world code? Seems like it might be kind of risky.
Ditto. I’ve certainly never used it and can’t recall seeing it in any codebases I’ve worked on or looked at. Sounds interesting though!
I’ve of course certainly heard of, seen, and used `assert`, but more often than not, outside of pytest, I see its use way more in potential footgun scenarios—I doubt that many people know that assertions can be silenced, and that they’d probably be better off raising exceptions in many cases where they’re using `assert`.
I feel like it's the kind of thing you might wind up caring about if you're micro-optimizing your python, but in my experience that's a losing game and you're better served rewriting it in another language than bothering with trying to speed up the execution of the raw python code (it's not that you can't optimize python code, but only in broader strokes. If you are looking at the bytecode you're in too deep and every time I've seen it tried the code has been ported shortly afterwards).
I see asserts used in production code as part of flow control way too frequently, so I assume the majority of python users aren't aware of the -O flag, much less this behavior- which I too haven't ever heard of.
Of recently, I've noticed claude is a big fan of asserts too.
Misery is trying to retrofit "bool", True/False, and nil/null to a language. C had to do that. Python had to do that. Getting those wrong is one of the classic language design mistakes. It seems like treating "True" as a value that equates to 1 will work, but then the special cases get you. Like being able to perform arithmetic on True.
Common language design boners:
- Not building in strings. That's now in the past. Everybody has strings. (Well, C...)
- Not building in multidimensional arrays of the numeric types. Everything that number-crunches needs them, and having multiple definitions is Not Fun and may lead to expensive re-copying between different libraries.
This is an enormous blind spot in language design. It's one of the reasons FORTRAN, which has good multidimensional numeric arrays, is still often used for number-crunching.
- Not standardizing the small vectors (vec2, vec3, vec4) and their matrix friends. Graphics code depends on these, and it's really annoying if there are multiple slightly incompatible implementations. Especially since GPUs have hardware for those types, and you want CPU and GPU to use the same representations.
- Not having arrays of bits. Pascal had PACKED ARRAY[0..N] of BOOLEAN but that was lost in later languages. It's useful to have that as a language construct, because most modern CPUs have good hardware for dealing with bit strings, and you'd like the compiler to use it.
Most useful languages acquire these features, but, when they come in late, there are multiple similar implementations, and libraries made incompatible by depending on different implementations.
(Amusingly, when Second Life switched from Linden Scripting Language to Luau, they initially had True, TRUE, and true all in use, as different types with different semantics. I was able to persuade the devs to unify the boolean types.)
> Not having arrays of bits. Pascal had PACKED ARRAY[0..N] of BOOLEAN but that was lost in later languages. It's useful to have that as a language construct, because most modern CPUs have good hardware for dealing with bit strings, and you'd like the compiler to use it.
I'm not sure exactly which features are responsible (I'm inclined to blame templates), but C++'s std::vector<bool> is a rough edge. For those unfamiliar, the standard specifies this vector template in a way that's not compatible with other vectors.
I don't. I have no interest in trying to assign a value to something that's built-in and not meant to be written to. Like who fucking cares that the boolean constants are actually weird little structure that sometimes let you mess with them and other times your edits are ignored? Maybe this is helpful for writing an entry for an obfuscated code challenge but I'm not doing weird shit like that with the code I expect to work between various Python versions and implementations, especially when I'm getting paid to do it.
Please. Such a charged response wasn’t justified at all. Different people are curious about different things. You ask “who fucking cares?”. The answer? You don’t, and the person you’re replying to does.
I used to like Python in the 2010s when it felt like a breath of fresh air relative to PHP and Perl.
Now it feels like a weird PHP itself that is slow, brittle, and dangerous to write code at scale in.
The loose typing, potluck standard library, and horrible package manager (insofar as the community does not know how to package code) all feel so dated.
I felt the same way about moving to Python versus PHP and Perl.
I still really enjoy using python though. It's not really a fair comparison because I hadn't used PHP and Perl for as long but I just don't hit some mystifying issue every single session like I did with those languages when I'm using python. I honestly have never even read about that __debug__ constant. It's fun to hear about it but it's just not something that's comes up much.
Perl is a lot like that also, you can read about some really weird old features like $[ but you never see that in practice, you just write code with variables and functions and so on.
I keep on hearing people be excited about PHP. Having first attempted to use PHP in early 00s, I simply cannot bring myself to attempt it again. I once had to rewrite large chunks of a site because it simply couldn't deal with the fact that a string had an apostrophe in it.
PHP has evolved a lot, but it also still has a lot of cruft from its earlier days. And it has made breaking changes on a scale python probably couldn't get away with.
Python certainly has some baggage, especially the typing system (which is still not finished, if you're looking at static typing and so is implemented differently by type checkers) and pip's safety, or lack thereof. But comparing it to PHP or Perl is rhetoric leading you one step too far.
Comparing it with PHP is unfair… to PHP. The amount of hard work that the PHP community has done to advance and keep their language relevant is impressive and admirable, and Python is perhaps the most extreme counterexample there is.
The Python community has spent the last 15 years refusing to improve in any meaningful way, or to learn anything from their peers. As someone who used to choose only jobs that would let me work with Python, I’ve gone through every phase of grief, and now just try to forget that it exists.
Lol, Python has had incredible improvements over the last decade plus, while uv fixed packaging. It's the best/comprehensive glue language ever made, even with a few remaining warts.
Most of the time downvoters don't explain their downvote, but I'll explain mine. I voted this comment down because it's just plain incorrect.I worked with PHP for nearly ten years (and I never want to go back). Maybe PHP has improved since I worked with it (PHP 7.4 was the most recent version when I last worked with it, I have never used PHP 8), but I doubt it.
But to describe the Python community as "spen[ding] the last 15 years refusing to improve in any meaningful way" is just laughably wrong. I can't give details as I haven't been doing much Python work, but even so I know of multiple changes, such as the typing system, or packaging improvements, which have significantly improved the language AFAICT. If there's a reason why you would not consider those to be "improv[ing] in any meaningful way", please enlighten me.
I don't understand how people talk about how Python is "easy to learn for beginners" or "easy to understand." To me it's so hard to remember and follow all the weirdness. Racket / Scheme / I dare say even Haskell would just be so much simpler for learners.
I'm with Conal Elliot when he said on Type Theory for All that it is sooo much harder to understand a program in Python.
I can understand that "advanced" python programs may be difficult to understand for beginners (lots of implicit/hidden behaviors, possibility to change basically everything one should expect, etc).
But to _learn_ programming, I really, really don't see how using Haskell would be simpler than Python. Perhaps if you have a specific background (e.g., math), but else python is almost pseudo code already. You'll really have to convince me that a more abstract language is better...
Haskell’s hard to interpret error messages alone disqualify it from being a beginner language.
Python: errors based on incorrect indentation (many beginners don’t use nice IDEs), or don’t understand the meaning of the hints) and scope (don’t forget your “global” if you’re hacking in PyGame) are challenges.
> Racket / Scheme / I dare say even Haskell would just be so much simpler for learners.
I have used all three languages; and you clearly have no idea of the notion of usability of a language. So many things contradict this, let me list them off the top of my head
- Getting a running toolchain working: Prexisting (most OSes bundle a Python interpreter) or a package install away for Python. Scheme / Racket is some odd mix of custom IDEs with Dr. in the name, or someone's 20 page essay on how SLIME is the best thing ever. Haskell gets into odd stuff with ghci, cabal, and stack, and all of them are extremely slow.
- Tutorials: Python has a ton of them, they all get you printing to stdout and calculating things in about 10 minutes. Scheme / Racket typically spends multiple chapters navel-gazing about lists, cons, and such. Haskell is actually better in terms of the Hello World stuff, but ghci v/s ghc bites you again; and no one has a clear idea of which one to use.
- Advanced concepts: Python has mainstream but halfhearted OOP; and things like decorators and metaprogramming. Quickly intelligible if you learned something else like Java or C++. Or if you learned shell scripts you can get quite a bit done with just imperative. Racket/Scheme: 3 chapters in and you're still trying to figure out tail recursion. Haskell: Instead of just doing fun things with take and foldl you're being hit with trivia about typeclasses.
I feel the same way. It was, back then “the second best language for everything, the first best at nothing”
Can’t take credit for the quote, read it somewhere.
The whole language changed when they kicked what’s-his-name out, and it’s a tool I almost never reach for anymore, whereas 15 years ago it was my Swiss Army knife.
Who cares tho. The agents deal with all of that, if you’re still looking at the code or caring about anything other than the loops and orbs you’re at the wrong level of abstraction. The important thing is the models have tons of python in their training data.
Don't mind the web designers calling themselves engineers.
There's a lot of annoying issues with Python, but compared to the billions of dollars and thousands of man hours that has been spent trying to fix Javascript and how horrible it still is, it's a perfectly cromulent language.
Ruby has such a nice holistic consistency to it. With a few exceptions, it feels like it was conceived of by one person with a core idea in mind. Python feels like a mess.
That said, I find it the nicest, cleanest option of the three. I still wouldn't use it for large and complex projects. I really like it for stuff where one might otherwise use shellscript. It's way way better than shellscript... except if it's all about files and running external commands.
In an age where people are still standing by C over memory-safe systems programming languages, I feel quite comfortable depending Python for the great many things that Python is good at.
For little utilities, it’s faster than a lot of alternatives - just start the interpreter, no compilation needed.
It’s all relative, but if you view it as replacing bash scripts for renaming files or running other tools, it’s 100x better.
We open sourced the implementation https://github.com/janushendersonassetallocation/loman
The fact that Python has become the language of choice for machine learning and data science is not a language issue.
If you've ever read through FORTRAN code from a mathematics department or MATLAB/C/C++ from (non-software) engineering disciplines, then you probably understand why productionizing a jupyter notebook is definitely not the worst of all possible worlds.
My CLI tools publish from Github to PyPI so that I can run tools with just `uvx sql-agent-cli` or `uvx dlna-here. Nothing for me to handle downloading (directly myself), no environment to manually setup, portable (Linux, Windows, Mac, ARM, x86). Easy for agents to run from a skill.md file without any other prereq than uv.
Really useful library ecosystem to leverage. No more shell scripts, or TS/JS/PHP backend services. I've even used Python on devices I've built around Raspberry Pi Zero 2 boards.
You didn't use Perl before? https://xkcd.com/353/
> I often work with data scientists and have to productionize their jupyter notebooks
I'm not a huge Python fan, despite working with it fulltime, but this feels like mixing correlation and causation. Data scientists would not be writing good, optimized code in any language.
> and it’s way too easy to do the wrong thing
is there another programming language where you believe a data scientist is going to have an easier time writing correct code than Python? Do you think C or Rust or JavaScript or C# make it harder to do the wrong thing?
Nice to see it get attention this time.
Assigning to __debug__ wouldn't do anything to the compiler as it never actually reads the variable, so assignment would just cause weirdness from other use
I’ve of course certainly heard of, seen, and used `assert`, but more often than not, outside of pytest, I see its use way more in potential footgun scenarios—I doubt that many people know that assertions can be silenced, and that they’d probably be better off raising exceptions in many cases where they’re using `assert`.
True = 1
False = 0
then later these got added to the language. In Python 2 you could still reassign and swap them so that 'if False' was actually true!
True, False = False, True
Python 3 you could no longer reassign them.
Common language design boners:
- Not building in strings. That's now in the past. Everybody has strings. (Well, C...)
- Not building in multidimensional arrays of the numeric types. Everything that number-crunches needs them, and having multiple definitions is Not Fun and may lead to expensive re-copying between different libraries. This is an enormous blind spot in language design. It's one of the reasons FORTRAN, which has good multidimensional numeric arrays, is still often used for number-crunching.
- Not standardizing the small vectors (vec2, vec3, vec4) and their matrix friends. Graphics code depends on these, and it's really annoying if there are multiple slightly incompatible implementations. Especially since GPUs have hardware for those types, and you want CPU and GPU to use the same representations.
- Not having arrays of bits. Pascal had PACKED ARRAY[0..N] of BOOLEAN but that was lost in later languages. It's useful to have that as a language construct, because most modern CPUs have good hardware for dealing with bit strings, and you'd like the compiler to use it.
Most useful languages acquire these features, but, when they come in late, there are multiple similar implementations, and libraries made incompatible by depending on different implementations.
(Amusingly, when Second Life switched from Linden Scripting Language to Luau, they initially had True, TRUE, and true all in use, as different types with different semantics. I was able to persuade the devs to unify the boolean types.)
I'm not sure exactly which features are responsible (I'm inclined to blame templates), but C++'s std::vector<bool> is a rough edge. For those unfamiliar, the standard specifies this vector template in a way that's not compatible with other vectors.
https://github.com/nucypher/constantSorrow/blob/master/tests...
Now it feels like a weird PHP itself that is slow, brittle, and dangerous to write code at scale in.
The loose typing, potluck standard library, and horrible package manager (insofar as the community does not know how to package code) all feel so dated.
I still really enjoy using python though. It's not really a fair comparison because I hadn't used PHP and Perl for as long but I just don't hit some mystifying issue every single session like I did with those languages when I'm using python. I honestly have never even read about that __debug__ constant. It's fun to hear about it but it's just not something that's comes up much.
The Python community has spent the last 15 years refusing to improve in any meaningful way, or to learn anything from their peers. As someone who used to choose only jobs that would let me work with Python, I’ve gone through every phase of grief, and now just try to forget that it exists.
But to describe the Python community as "spen[ding] the last 15 years refusing to improve in any meaningful way" is just laughably wrong. I can't give details as I haven't been doing much Python work, but even so I know of multiple changes, such as the typing system, or packaging improvements, which have significantly improved the language AFAICT. If there's a reason why you would not consider those to be "improv[ing] in any meaningful way", please enlighten me.
I'm with Conal Elliot when he said on Type Theory for All that it is sooo much harder to understand a program in Python.
But to _learn_ programming, I really, really don't see how using Haskell would be simpler than Python. Perhaps if you have a specific background (e.g., math), but else python is almost pseudo code already. You'll really have to convince me that a more abstract language is better...
Python: errors based on incorrect indentation (many beginners don’t use nice IDEs), or don’t understand the meaning of the hints) and scope (don’t forget your “global” if you’re hacking in PyGame) are challenges.
I have used all three languages; and you clearly have no idea of the notion of usability of a language. So many things contradict this, let me list them off the top of my head
- Getting a running toolchain working: Prexisting (most OSes bundle a Python interpreter) or a package install away for Python. Scheme / Racket is some odd mix of custom IDEs with Dr. in the name, or someone's 20 page essay on how SLIME is the best thing ever. Haskell gets into odd stuff with ghci, cabal, and stack, and all of them are extremely slow.
- Tutorials: Python has a ton of them, they all get you printing to stdout and calculating things in about 10 minutes. Scheme / Racket typically spends multiple chapters navel-gazing about lists, cons, and such. Haskell is actually better in terms of the Hello World stuff, but ghci v/s ghc bites you again; and no one has a clear idea of which one to use.
- Advanced concepts: Python has mainstream but halfhearted OOP; and things like decorators and metaprogramming. Quickly intelligible if you learned something else like Java or C++. Or if you learned shell scripts you can get quite a bit done with just imperative. Racket/Scheme: 3 chapters in and you're still trying to figure out tail recursion. Haskell: Instead of just doing fun things with take and foldl you're being hit with trivia about typeclasses.
Can’t take credit for the quote, read it somewhere.
The whole language changed when they kicked what’s-his-name out, and it’s a tool I almost never reach for anymore, whereas 15 years ago it was my Swiss Army knife.
for all the hate js used to get, py is at least a few magnitudes worse.
my opinion ofc. don’t get mad xD
There's a lot of annoying issues with Python, but compared to the billions of dollars and thousands of man hours that has been spent trying to fix Javascript and how horrible it still is, it's a perfectly cromulent language.
Did you encounter JS first?