4 ms·
My experience is pretty negative with all of them, I would be almost more tempted to ignore type checking in Python until it has drastically improved. In partic
by MrJohz 3y ago
My experience is pretty negative with all of them, I would be almost more tempted to ignore type checking in Python until it has drastically improved. In particular, if you're experienced with Typescript, you're probably going to be very disappointed when trying to do similar things in Python.
The most recent one I've tried was Pyright. Pyright is faster than Mypy, and can also be configured to be quite strict, both big plus points for me. Unfortunately, in practice it ended up being far too strict in weird ways, and therefore difficult to work around with libraries that don't share its idiosyncratic assumptions.
For example, in Typescript there's an unknown type, which you can't do anything with unless you check its runtime type first. It's a clever way to add a true dynamic type to the type system without losing type safety. In Pyright there's a similar Unknown type, but in strict mode the type checker simply throws an error if anything is ever unknown. For me, this turned out to be particularly painful when using library types that involved generic state. Because I wasn't using that state, I didn't set a type for it, and it defaulted to Unknown. But that meant that an object had Unknown properties (that I was never using) which meant the type checker kept on failing. Moreover, because Python's generics story is pretty miserable, I couldn't figure out how to set the type to something not Unknown. And I couldn't figure out how to disable the error because Pyright's documentation is so poor. I genuinely spent a day of work on this problem, then disabled type checking completely because that was the easiest option.
I haven't used Mypy for over a year at this point, so things may well have changed, but my memory was that where Pyright is overly pedantic, Mypy was overly lax. It was also a lot slower, and had similarly poor documentation. The main reason I switched was that I was still regularly running into runtime type errors - the very errors that the type system was meant to help me avoid.
In both cases, I found the biggest problem was that neither tool seemed to go as far as Typescript in terms of modelling real-world Python code. What I mean by that is that idiomatic Typescript usually looks a lot like idiomatic Javascript in terms of the patterns and features used, because the Typescript team have put a lot of effort in to ensure that Typescript types represent how Javascript is actually used.
On the other hand idiomatic typed Python typically seems to look very different from idiomatic untyped Python, in large part because with types, you end up limited to about 1/4 of the surface area of the language. (This is why a lot of major libraries or tools come with type checker plugins because their library's behaviour cannot be described purely in terms of types.) Typed Python then ends up looking like a weird Java variant.
If I were going to add a type checker to my Python code again, I'd probably go for Mypy because it seems more like the standard and had marginally better documentation. But right now, I have the Pylance plugin installed in my IDE and that's about it - there's no type checking in CI, I just hope that I catch all the obvious cases with good enough testing. Thankfully the Python side of my work is pretty minimal, a few hundred lines of code at most. If I had a bigger Python project I might revisit this situation, but I'd be more tempted to just avoid Python for bigger projects.
- v3ss0n 3y agoVery good points. Did you also tried ignoring some rules that are overly strict? Or reduce them to warnings?
- MrJohz 3y agoThat was part of the wasted day I was talking about - trying to configure the system so that the rules would be more useful. I could disable the warnings per-line with comments - although this meant that my code was then filled with these lines and the formatting was awful - but I couldn't disable the warnings globally for some reason. I never managed to figure out why, unfortunately.
- v3ss0n 3y agoPer project is easy using PDM or Poetry.
- a-dub 3y agoi've often thought a more interesting approach for python's duck typing would be if the interpreter looked for anomalous types on assignment. so build a compact distribution of type "shape" for every assignment and then either throw exceptions or log warnings when apparent outliers are encountered.
- pepoluan 3y agoUse lots of typing.Protocol and you get all the goodness of duck-typing.
- MrJohz 3y agoThat's roughly a structural type system, and it's part of what makes Typescript work well (although it has some disadvantages in that you can't easily describe the type "an object with only these attributes). You can somewhat get that effect with Protocols in Python, but it often feels a bit boilerplate-y to me.
- 3y ago