As someone who has written Python for nearly 20 years now, and also has plenty of experience with strongly and statically typed languages (including a fair bit of Haskell), I think type hints in Python should at most remain just that, hints.
A language being statically typed or dynamically typed is a design decision with implications for what the language can do. There are benefits to each method of programming.
Trying to strap type checking on to Python is born out of some misplaced belief that static type is just better. Using Python as a dynamically typed language allows you for certain programming patterns that cannot be done in a statically typed language. There are some great examples in SICP of Scheme programs that could not exist (at least with as much elegance) in a typed language. Dynamic typing allows a language to do things that you can't do (as easily/elegantly) in a statically typed language.
Some may argue that these type of programming patterns are bad for production systems. For most of these arguments I strongly agree. But that means for those systems Python is probably a poor choice. I also think metaprogramming is very powerful, but also a real potential footgun. It would be ridiculous to attempt to strip metaprogramming from Ruby to make it "better", just use a language that depends less on metaprogramming if you don't like it.
This is extra frustrating because in the last decade we've seen the options for well designed, statically typed languages explode. It's no longer Python vs Java/C++. TypeScript and Go exist, have great support and are well suited for most of the domains that Python is. Want types? Use those languages.
Have to disagree with this. Choosing a language is not just about its features but also its ecosystem. I chose Python for my current project because it has great libraries that don't exist in other languages.
"my current project" type problems are where Python is great. Types remain "nice to have" (if you like them) and aren't really essential compared to the ease of prototyping new ideas and building a PoC. You're choosing Python because the benefit of libraries outweighs your personal preference for types.
Most of my work is in machine learning/numeric computing, so I'm very familiar with the benefits of Python's ecosystem. Basically all of AI/ML work is about prototyping ideas rapidly, where access to libraries and iterating fast greatly trumps the need for type safety.
At nearly every place I've worked, Python is the tool for building models quickly but shipping them to production and integrating them with the core product almost always involves another language, typically with types, better suited for large engineering teams working on a large code base where you really want some sort of type checking in place. Most of the companies I know that do serious ML in production typically take models from python and then implement them in either C++ or Scala for the actual production serving.
It's worth pointing out that the vast majority of those libraries you use were initially developed without any consideration, or need, for types. Great, reliable, software can be written without types. Dynamic typing is a great language choice, and there's no need to fight the language itself by trying to bolt types on.
Where types are important is where you have a complex, rapidly changing code base with a large number of developers of differing skill levels releasing frequently. If that's the environment you're in, I would strongly recommend against using Python in prod, even if it means you have to implement the features of some libraries internally.
You keep saying how typing prevents some "elegant" things (are they really prevalent?) or "iterating fast greatly trumps the need for type safety". But in my experience, anything more than half a dozen modules/classes can turn into a bloody minefield very fast. And the supposed speed of iteration is negated and reversed by having to dig through the untyped codebase trying to very inefficiently determine the types manually, with my own eyes, as to not screw up. What are those supposed super-benefits of ditching type safety?
> anything more than half a dozen modules/classes can turn into a bloody minefield very fast
I don't disagree with this, but it's worth noting that there are many data scientists I've worked with who have never written a python class or module, and yet produced large amounts of valuable work.
For quick prototyping and exploratory work, both domains where Python sees a lot of success, it's often the case that you don't really know what types you're working with and are iterating very quickly, such that not being able to quickly change all of the types your working with can be a time sink.
So I think you're imagining writing software that is starts more well defined than most optimal use cases for Python.
> And the supposed speed of iteration is negated and reversed by having to dig through the untyped codebase trying to very inefficiently determine the types manually
I do understand this feeling, but this is applying the logic/patterns of statically typed programming dynamic programming. The dynamic answer to "how do I write robust code" is not to keep the types in your head, it's write tests. Well written tests in turn become documentation for your code.
Again, this style of programming works well when you don't really even know how you want your programming to behave. You naturally write tests when writing this kind of code, even if it's just manual tests. Get in the habit of starting your manual tests as unit tests and you're already doing TDD.
Dynamic types works best when you are writing code in a very interactive and exploratory way.
To be clear: I'm not advocating for dynamic languages over statically typed ones. I do believe, whenever possible, production software should be written in strongly typed languages. I think anytime you know the behavior of your program before you start writing you should use statically typed languages.
Last thing I want is Go types tbh. Trying to figure out what implements a given interface is difficult without a sufficiently clever tool.
Funnily enough, Python has Go-esque types also, Protocols, and they have the exact same issue. I only use them when I really really need structural typing to reuse code in a typesafe way.
Autocomplete and type-checking are massive boons to writing "type-correct" code, fast. It doesn't guarantee that your code won't explode at runtime or is logically correct (that's what tests are for), but it does help eliminate an entire class of bugs, and, again, speeds up development a massive amount when dealing with very large codebases.