As a long time Python fan, I find the current state of the language frustrating. Tools like black and poetry are nice, but are not part of the standard library. Yet they seem to be required by every popular project out there. (Also, black’s formatting is quite ugly, as noted in this blog post)
Meanwhile, the language itself is increasingly baroque and complicated. Type-annotated, asyncio-enabled Python hardly resembles the easy-to-understand language I fell in love with back in 2006.
Perhaps this is just an “old man yells at cloud” moment...
> Tools like black and poetry are nice, but are not part of the standard library.
If black does non-PEP 8 formatting, as the article says, then I would not expect it to be in the standard library, since PEP 8 formatting is the Python standard.
> the language itself is increasingly baroque and complicated
I don't find current Python 3 any more baroque or complicated than Python 2.7. In fact I have plenty of Python code that runs just fine, unmodified, under both interpreters. And I have plenty of other Python code that only needs from __future__ import print_function to run unmodified under both interpreters.
That's not to say I think there are no issues with current Python 3; just that I wouldn't describe those issues as "the language is increasingly baroque and complicated". See further comments below.
> Type-annotated, asyncio-enabled Python hardly resembles the language I fell in love with back in 2006.
You don't have to use these features if you don't want or need them. Nobody uses 100% of any language's features, and the subset that is used can be very different from person to person. I don't see that as a problem.
I did see the way the Python 3 transition was handled as a big problem, but that's water under the bridge now and the issues that gave many people headaches during the transition were pretty much resolved by Python 3.3.
The two big problems I see with current Python 3 are memory usage and the GIL. Python 3 objects take more memory than Python 2 objects did; for programs that create a lot of objects that can be an issue. (To be fair, many such programs are numerical simulations that can take advantage of the many optimizations in the NumPy and SciPy libraries.) There seems to be work in progress on supporting multiple interpreters running in the same Python process, which would fix the GIL issue, but it's too soon to see if that will really address the issues surrounding the GIL.
> You don't have to use these features if you don't want or need them. Nobody uses 100% of any language's features, and the subset that is used can be very different from person to person. I don't see that as a problem.
The problem is that other people might use those features and you also might have to read the code created by those people.
It's just one more thing you have to get to learn.
I have the same problem with classes in JavaScript. You can't ignore them and stick to prototypes nor ignore prototypes and stick to classes. What should have been a simplification has turned out to make things more complex.
Unlike ES6 classes, you absolutely can ignore type hints (and they're easy to ignore). In fact they're basically inline comments, and the interpreter ignores them too.
I have to disagree regarding asyncio. If existing code uses it that you need to interface with, your sensible options are basically to rewrite all of your code to use asyncio, or try a hacky third-party library that'll try to bridge them.
I'm personally not a fan of it (I'm still a gevent proponent; Go seems to be doing fine with a green thread model), but a lot of libraries I use are written with it, so it's pretty annoying for me. That and the dependency/package story are the two things that've made me seriously consider switching to a different language. (The article's complaints about things like pre-commit and isort are pretty silly and irrelevant, IMO, though it would be nice if there was something official like "go fmt".)
So far the benefits still outweigh the costs for me, compared to other languages, but I predict a better, cleaner, and more performant successor to Python may come this decade. If it does, I think I might become an early adopter.
> I have to disagree regarding asyncio. If existing code uses it that you need to interface with, your sensible options are basically to rewrite all of your code to use asyncio, or try a hacky third-party library that'll try to bridge them.
Yes, this is true. I don't think there's a lot of existing code using it at this point since it's still a fairly new feature. But of course that will change as time goes on.
> I'm personally not a fan of it
I haven't tried it yet in an actual project, but my initial reactions just looking at the specifications and examples were mixed. I like the idea of the await keyword to label call sites where your code might be suspended, but I don't like having "async" cluttering up function definitions, for loops, and with statements. The way generators were handled when they were first introduced in Python 2 was much cleaner IMO: one new keyword, yield, and any function that had that keyword in it automatically became a generator. I don't see why a similar rule couldn't have been implemented for the await keyword: any block with await in it automatically becomes an async block.
I do find the mandatory "async" peppering everywhere annoying, but I'm honestly not a fan of the whole paradigm. I don't actually think it's that important to explicitly specify "await" when you want to await. It's also extremely prone to obscure, frequently-missed errors; a missing await or unnecessary/incorrect await can affect performance or logic in a massive way.
There are massive differences between languages, though. I think I might use close to 70% of Objective-C's or Java's features regularly, while I can't even hope to use 50% of C++'s.
> Type-annotated, asyncio-enabled Python hardly resembles the easy-to-understand language I fell in love with back in 2006.
true.
i am all for types in general and for types annotations in python. but i have seen some heavily type-annotated python code lately and i don't think that's where we want to be.
we are starting to look like a heavily templatized cpp code.
Type annotations help catch common errors, and they help humans. Maybe it's not as pretty but as someone who often have to read Python, it really helps me understand what the contract is of a function I'm looking at.
As a big fan of statically typed languages, I agree with you on the utility. Especially after having worked on a large Python projects a few years ago and having to spend a lot of time figuring out what, exactly I could do with a argument named “session”. But when you start turning your dynamically types languages into an ugly statically typed one, maybe we should just admit that we’re using the wrong tool for the job.
Is the point where your Python codebase needs type hinting to be readable a signal that you've hit the dynamic language/complexity impedance mismatch?
Or is it a sign that your code's readability could be better?
Your "session" remark reminds me of trying to understand the Ruby IMAP library when the only documentation was autogenerated API docs, I had to follow one variable through the entire stack to figure out what it's original type and thus capability, was.
I taught myself to code in Python, and find that well-written Python makes sense without types (tooling support aside), but then being honest, most of the Python code I meet professionally, is barely okay written.
I guess it's like Java, industrial programming code needs a type system to make code written averagely understandable, but not so much of a type system that you spend your time fighting obscure compiler errors.
Don't mix things, guy!
- asyncio it's one thing: From my point of view it's amazing... makes python be able to compete with nodejs or go.. (not so hard, if you work also on the browser)
- mypy: that's another story, but it's also optional, use it if you want... (my opinion, like in typescript, if I want types I will do it with go or rust)
Honestly, after trying MyPy for a bit, I'm probably going to gradually type. There's some metaprogramming constructs (notably certain class decorators) that are not expressible in the type system, for one. This makes packages like environ-config unusable.
But most importantly, `def foo(lst: list, idx: int):` is fine in 95% of cases. Most of the time, you don't need to go full Java, full verbosity. Document the most important elements - you're taking in a list and an int - and move on.
(Though yeah templates in C++ turn the ugliness to 11)
Not to mention Python is "strongly-typed". But it doesn't require variables to have a pre-determined type and doesn't do compile time type checks by itself.
I think this can be the curse of popularity. The demand from more and more users of different feature, especially backed by industries who rely on the language, means that slowly over time, all popular languages accumulate scope and feature creep to some extent.
But at the same time, for serious industry work, those features do come in handy when you do need them.
I think this is why to some extent you never hear that much good of the old tried and tested languages. They always feel bloated, disorganized, confusing, with too much cruft, and yet it's all that which make them what they are.
> Type-annotated, asyncio-enabled Python hardly resembles the easy-to-understand language I fell in love with back in 2006.
I'm all with this, but you can pretty much use python without touching these at all. They have a niche business use cases. E.g., when you work on large projects and you want to catch some errors to not be in the runtime.
async was very needed to be able to write performant web servers such as nodejs.
I'm not using python as i used to, and i think the language is getting more complex, and i'd definitely vow for more fundamental changes to the runtime. But if you ignored all of that, python is still remain python. And when your business logic gets more complex, it is imperative your code becomes more complex and you get to discover and use more "language advanced features". The good thing they are available, they are not perfect, but they can be of a good help.
Perhaps this is just an “old man yells at cloud” moment...
Fellow "old man" reporting for duty.
I see a similar set of problems with both Python and JavaScript today (and with various other languages as well, but IME Python and JS are the worst offenders). Both have proven to be useful for various applications. Each started with quite a distinctive style. There were plenty of warts in each case, but overall the "feel" of each language was well understood, and there was a certain simplicity about them that made them accessible to new programmers or to programmers who primarily used other languages. However, over time, people have applied the kitchen sink approach to both language and tooling.
Functional programming is all the rage, and these languages have lambdas (albeit very clumsy ones), so let's all write lots of FP-style code in them! Except you can't, because they are horrible for writing FP-style code, because they lack FP features, they lack efficient and clear syntax for FP idioms, and they do not provide some of the guarantees that benefit FP.
Similarly, a lot of programmers are realising that static typing has its merits when you're trying to build serious software at scale, so let's all add type annotations and start marking up our code! Except that both the existing type systems and idiomatic use of these languages are built around dynamic behaviour, so they lack powerful tools for constructing new types, and they lack efficient and clear syntax for specifying static types, and they lack comprehensive type inference, and the continued presence of dynamic typing means you can't prove a lot of otherwise useful properties of your code anyway.
The amount of tooling expected to do even basic development with these languages today is absurd. Professional-quality programming ought to need no more than a compiler/interpreter, a decent editor and a decent source control system to be productive. On the next level, we might find a tool to automate running tests and reporting the results, a debugger and a profiler; I count these as secondary because it should really be possible to work reasonably well without them but they can make common tasks significantly more efficient and/or accurate. The lack of a package manager tool in both of these lists is not an accident.
I think just as much of today's programming industry has forgotten about the benefits of stability, backward and forward compatibility, and standardisation in the software we make, we have also forgotten about them in our own tools. Do we really need 27 new frameworks for building web apps this year? Is having 41 libraries to do basic unit testing that each use slightly different syntax and vary in <5% of the features they provide really worth the added complexity in the ecosystem? How on earth does JS not have a decent standard library yet?
Maybe it's time to slow down, and make carefully considered choices about the tools and libraries we use in our work, instead of instinctively reaching for that package manager and installing... well, let's be honest, most of the time we don't really know exactly what we're installing, do we?
not the OP but I share the sentiment. On a syntax level simply because it adds types, and one of the joys of writing a dynamic language is that you don't have types filling so much of your code.
But much more important to me, on a semantic level. Late binding of all things is a feature of dynamic languages, not a bug. I have no idea why we're trying to force a static typing mindset onto a dynamic language.
I wish we could all remember that the original idea of OO is that objects interpret the messages they receive, not external typecheckers.
> On a syntax level simply because it adds types, and one of the joys of writing a dynamic language is that you don't have types filling so much of your code.
Then good that you don't have to do that. Type hinting in python is optional and it's unlikely that this will ever change.
> I have no idea why we're trying to force a static typing mindset onto a dynamic language.
Because python ist not a toy-language anymore. It's used for big projects too, and for them features like this are very neccessary.
>Because python ist not a toy-language anymore. It's used for big projects too, and for them features like this are very neccessary.
I've worked on multi-million line dynamic codebases in settings that require robustness and correctness (telecommunications/Erlang) and it's an absolute ridiculous idea that one needs type checking to build industry standard codebases and architecture.
The Java/C++ paradigm is not the only software paradigm to built correct software.
print as a function and headache-inducing string handling hardly resemble the python I came to like either. those two things bring python3 down from great to meh for me. biggest language change blunders I've ever seen. I feel a wave of disappointment every time I have to type a paren on a print call in python3.
yessss... because a pair of parentesys are too much... I always hated that I couldn't pass "print" as a callback, or the weird >> syntax to write on stderr
> hardly resembles the easy-to-understand language I fell in love with back in 2006.
I used to love Python back in those days. Even did a big project with multiple developers in it.
Then I didn't use it for a while and came back for some easy scripting. I was absolutely horrified how complex things are right now. Ditched it and doing my scripting with node.js.
Seriously, how F(&#$%@ING complex can you make the thing?
This is Javascript:
JSON.parse(text[, reviver])
Ah, that's the way I like it :)
But hey, if you want all that argument power, no problem for me. I'm a simple programmer, liking simple things. And that was my point, Python has lost its simple ways. The JavaScript language might have some weird shit, but I don't care about that because I can stay far away from it. I care about simple programming.
ahahahah
now you are telling me that the node ecosystem and the tooling and pre/post compilation/translation phases are simpler than python? (and I'm not talking about the languages themself)
what do you call the various phases of bundling, minification, obfuscation...?
or using babel to use the latest version of the spec?
or the various passages of type/coffescript and whatnot...
or the jsx stuff...
or wasm, webassembly...
... and on and on...
Meanwhile, the language itself is increasingly baroque and complicated. Type-annotated, asyncio-enabled Python hardly resembles the easy-to-understand language I fell in love with back in 2006.
Perhaps this is just an “old man yells at cloud” moment...