Comment by viccis

1 day ago

>with a better type system than either

Given Python's substantial improvements recently, I would put it far ahead of the structural typing done in Go, personally.

Strong agree here. I learned Go after having worked in large typed Python code bases, and Go feels like a HUGE step backwards typing-wise.

Yes, Python is massively ahead there. The largest wart is that types can be out of sync with actual implementation, with things blowing up at runtime -- but so can Go with `any` and reflection.

Python, for a number of years at this point, has had structural (!) pattern matching with unpacking, type-checking baked in, with exhaustiveness checking (depending on the type checker you use). And all that works at "type-check time".

It can also facilitate type-state programming through class methods.

Libraries like Pydantic are fantastic in their combination of ergonomics and type safety.

The prime missing piece is sum types, which need language-level support to work well.

Go is simplistic in comparison.

  • This. Both Typescript and Python type systems are way far ahead, with structural typing, exhaustive checks and much more.

  • As long as none of the code you wrote ten years ago is worth anything, and you don't expect to want to use the code you're writing today ten years from now. Python is useful for prototyping.

Python type system is very good. It’s enforcing it consistently that’s bad. Thankfully most new libraries are typed.

Python with a library like Pydantic isn't bad—I wouldn't rate base Python as being near Go's level, at all, though you can get it up to something non-painful with libraries.

Go (and lots of other languages...) wreck it on dependency management and deployment, though. :-/ As the saying goes, "it was easier to invent Docker than fix Python's tooling".

  • Yeah I think, given its gradual typing approach, that any discussion about the quality and utility of Python's type system assumes that one is using one of the best in class type checkers right now.

    I didn't really use it much until the last few years. It was limited and annoyiongly verbose. Now it's great, you don't even have to do things like explicitly notate covariant/contravariant types, and a lot of what used to be clumsy annotation with imports from typing is now just specified with normal Python.

    And best of all, more and more libraries are viewing type support as a huge priority, so there's usually no more having to download type mocks and annotation packages and worry about keeping them in sync. There are some libraries that do annoying things like adding " | None" after all their return types to allow themselves to be sloppy, but at least they are sort of calling out to you that they could be sloppy instead of letting it surprise you.

    It's now good and easy enough that it saves me time to use type annotations even for small scripts, as the time it saves from quickly catching typos or messing up a return type.

    Like you said, Pydantic is often the magic that makes it really useful. It is just easy enough and adds enough value that it's worth not lugging around data in dicts or tuples.

    My main gripe with Go's typing has always been that I think the structural typing of its interfaces is convenient but really it's convenient in the same way that duck typing is. In the same way that a hunter with a duck call is the same as a duck with duck typing, a F16 and a VCR are both things that have an ejection feature.