leading me to just disable the type checker altogether.
The better option is to just put # type: ignore on the statements where it gets confused, and add hints for your code. I’ve done that for SQLAlchemy before they got proper type hinting, and it worked pretty well.
That said, a type hint is just that, a hint. It shouldn’t be relied on to be 100% accurate (i.e. lots of foo: list should actually be foo: list | None), but if you use a decent static analysis tool, you should catch the worst of it. We use pyright, which is built in to the VSCode extension pylance. It works incredibly well, though it’s a bit too strict in many cases (e.g. when things can be None but generally aren’t).
So yeah, never blindly trust type hints, but do use them everywhere. The more hints you have, the more the static analysis can help, and disabling them on a case-by-case basis is incredibly easy. You’ll probably still get some runtime exceptions that correct type checking could have caught, but it’s a lot better than having a bunch of verbose checks everywhere that make no sense. A good companion to type checks is robust unit test cases with reasonable data (i.e. try to exercise the boundaries of what users can input).
As it stands, we very rarely get runtime exceptions due to poor typing because our type hints are generally pretty good and our unit test cases back that up. Don’t blindly trust it, and absolutely read the docs for anything you plan to use, but as long as you are pretty consistent, you can start making some assumptions about what your data looks like.
I really do agree on all your points, so at the end of the day I think a lot comes down to use-case and personal preference.
My primary use cases for Python are prototyping and as a frontend/scripting tool for software written in C/C++/Fortran. In those scenarios, spending significant time on type hinting and unittests defeats the purpose of using Python (blazing fast development).
I’ve written/worked on only one larger code base in pure Python, and my personal opinion became that I heavily prefer strictly typed languages once the code base exceeds a certain size. It just feels so much smoother to work with when I have actual guarantees that are enforced by the language.
With that said, we were a bunch of people that are used to using Python for prototyping that developed this larger library, and it would probably have gone a lot better if we actually enforced use of proper type hinting from the start (which we were not used to).
I heavily prefer strictly typed languages once the code base exceeds a certain size
As do I, but we don’t all get to pick our stack.
I use Rust for all my personal projects unless I have a good reason to pick something else. I like pretty much everything about it, from the lack of classes (I hate massive class hierarchies) to the borrow checker to everything being an expression. It feels like I’m getting most of the benefits of functional programming, without being tied down to FP to solve problems.
That said, I think Python is a reasonable choice for large codebases. For simple scripts, I generally don’t bother with type hints. At my current company, our largest codebase is well over 100k lines of Python, so the type hints are absolutely welcome since they help document code I haven’t touched in over a year (if ever). If things get slow, there’s always the option of a native module. But for most things, Python is fast enough, so it’s no big deal. Because of this, I use type hints for anything that might become a larger project. After the initial POC, I’ll go through and update types, fix a bunch of linting warnings/errors, and flesh out the unit tests. That way I have something to build from when I inevitably come back to it in a year or so.
So yeah, I definitely recommend using type hinting. The best time to add type hints is at the start of development, the next best time is now.
If my Easter break gets boring I might just start cleaning up that Python library… It’s the prime example of something that developed from a POC to a fully functional code base, was left largely unused for about a year, and just the past weeks has suddenly seen a lot of use again. Luckily we’re strict about good docstrings, but type hints would have been nice too.
The better option is to just put
# type: ignore
on the statements where it gets confused, and add hints for your code. I’ve done that forSQLAlchemy
before they got proper type hinting, and it worked pretty well.That said, a type hint is just that, a hint. It shouldn’t be relied on to be 100% accurate (i.e. lots of
foo: list
should actually befoo: list | None
), but if you use a decent static analysis tool, you should catch the worst of it. We usepyright
, which is built in to the VSCode extensionpylance
. It works incredibly well, though it’s a bit too strict in many cases (e.g. when things can beNone
but generally aren’t).So yeah, never blindly trust type hints, but do use them everywhere. The more hints you have, the more the static analysis can help, and disabling them on a case-by-case basis is incredibly easy. You’ll probably still get some runtime exceptions that correct type checking could have caught, but it’s a lot better than having a bunch of verbose checks everywhere that make no sense. A good companion to type checks is robust unit test cases with reasonable data (i.e. try to exercise the boundaries of what users can input).
As it stands, we very rarely get runtime exceptions due to poor typing because our type hints are generally pretty good and our unit test cases back that up. Don’t blindly trust it, and absolutely read the docs for anything you plan to use, but as long as you are pretty consistent, you can start making some assumptions about what your data looks like.
I really do agree on all your points, so at the end of the day I think a lot comes down to use-case and personal preference.
My primary use cases for Python are prototyping and as a frontend/scripting tool for software written in C/C++/Fortran. In those scenarios, spending significant time on type hinting and unittests defeats the purpose of using Python (blazing fast development).
I’ve written/worked on only one larger code base in pure Python, and my personal opinion became that I heavily prefer strictly typed languages once the code base exceeds a certain size. It just feels so much smoother to work with when I have actual guarantees that are enforced by the language.
With that said, we were a bunch of people that are used to using Python for prototyping that developed this larger library, and it would probably have gone a lot better if we actually enforced use of proper type hinting from the start (which we were not used to).
As do I, but we don’t all get to pick our stack.
I use Rust for all my personal projects unless I have a good reason to pick something else. I like pretty much everything about it, from the lack of classes (I hate massive class hierarchies) to the borrow checker to everything being an expression. It feels like I’m getting most of the benefits of functional programming, without being tied down to FP to solve problems.
That said, I think Python is a reasonable choice for large codebases. For simple scripts, I generally don’t bother with type hints. At my current company, our largest codebase is well over 100k lines of Python, so the type hints are absolutely welcome since they help document code I haven’t touched in over a year (if ever). If things get slow, there’s always the option of a native module. But for most things, Python is fast enough, so it’s no big deal. Because of this, I use type hints for anything that might become a larger project. After the initial POC, I’ll go through and update types, fix a bunch of linting warnings/errors, and flesh out the unit tests. That way I have something to build from when I inevitably come back to it in a year or so.
So yeah, I definitely recommend using type hinting. The best time to add type hints is at the start of development, the next best time is now.
If my Easter break gets boring I might just start cleaning up that Python library… It’s the prime example of something that developed from a POC to a fully functional code base, was left largely unused for about a year, and just the past weeks has suddenly seen a lot of use again. Luckily we’re strict about good docstrings, but type hints would have been nice too.
Woo, do it! And add some tests while you’re at it in case those don’t exist.
I found a few bugs just going through and cleaning up missing code coverage. Maybe you’ll find the same!