[HN Gopher] Python's "type hints" are a bit of a disappointment ...
       ___________________________________________________________________
        
       Python's "type hints" are a bit of a disappointment to me
        
       Author : zdw
       Score  : 71 points
       Date   : 2022-04-21 20:05 UTC (2 hours ago)
        
 (HTM) web link (www.uninformativ.de)
 (TXT) w3m dump (www.uninformativ.de)
        
       | daenz wrote:
       | Opinions like these are frustrating because, although they make
       | valid points, it comes off as "they didn't do 100% exactly what I
       | want, so I'm not using them at all." With many tools, there is a
       | middle ground between using them for everything, and not using
       | them at all. Python's type hints is one of those tools.
       | 
       | When I'm writing code, and a variable or signature is easy to
       | annotate, I'll annotate it. And guess what? MyPy occasionally
       | catches issues with my types and saves me some work. If a type is
       | very complex, I won't bother spending time annotating. The end
       | result is that I have some code that is annotated and prevents
       | simple errors, and other code that isn't, and I didn't spend much
       | time or effort doing it. To me, that's a clear net win.
        
         | bastardoperator wrote:
         | For me, I'm not writing huge programs in python, I may not need
         | type hints/safety right away, or at all, not that I'm against
         | them in any capacity. The problem I see with opinions like
         | these is the assumption that type checking/hinting/safety are a
         | silver bullet.
        
         | OccamsRazr wrote:
         | Yup.
         | 
         | > Despite all that, what I'm hoping for is that someone will
         | come along and tell me that I got it all wrong. "When you do it
         | as follows, the system works: $explanation" Because, you know,
         | I'd really like to have static typing in Python.
         | 
         | I want X. Y (which is designed for somthing other than X)
         | doesn't do X. Thus, I don't like Y.
        
         | patrick451 wrote:
         | Letting perfect be the enemy of the good is not the same thing
         | as doing a cost benefit analysis. In the authors estimation,
         | the costs outweigh the benefits. You don't seem to be
         | considering the cost of type checking at all.
        
         | davidhariri wrote:
         | Fully agree with this. Type _hinting_ (not checking) is
         | idiomatic to Python. MyPy is a great way to enforce checking.
         | It 's great to have the option to use the hints for
         | intellisense only.
        
           | mejutoco wrote:
           | My favourite way to enforce types in python is to use
           | typeguard's typechecked decorator. It is checked at runtime
           | but it can be added gradually.
           | 
           | https://pypi.org/project/typeguard/
        
           | throwaway81523 wrote:
           | I've found that even when I write code intended to be
           | statically checked from the beginning, mypy often misses
           | stuff. I was enthusiastic about mypy at first and I still use
           | it, but I'm not sure at this point that it is worth it.
        
             | the_af wrote:
             | Same here. And I come from (and am a fan of) statically
             | typed languages. The type hinting story for Python seems
             | confusing and not completely useful to me.
        
               | seti0Cha wrote:
               | I just started using type hinting in Python and I love
               | it. Maybe it's your tooling? I'm using neovim with LSP
               | and pyright and the experience is very much like writing
               | code in a Java IDE. As I code, it informs me where there
               | are mistakes or pieces of code that need to be updated,
               | catches typos, reminds me about forgotten imports, etc.
               | It makes refactoring way easier because as you change
               | signatures or object types it flags all the places in
               | your code that need to be updated. Seems like a real game
               | changer to me.
        
               | the_af wrote:
               | I want automated type checking outside the IDE. I want
               | something that will catch other programmer's mistakes,
               | not just mine. Without enforcing a specific IDE.
        
           | the_af wrote:
           | Honest question: what's the point of type _hinting_ without
           | type _checking_?
           | 
           | I must be mistaken, but I always thought "type hinting" was a
           | synonym of "optional type annotations". But if you're not
           | using those annotations for actual type checking _at some
           | point_ , what are they good for?
        
             | xarope wrote:
             | as a reminder for yourself/others who need to read/maintain
             | your code?
             | 
             | (I am often reminded of my perl days, where something I
             | thought idiomatic 3 days ago, is now completely
             | incomprehensible when I just want to make a minor change)
        
               | the_af wrote:
               | So is it simply a standardized comment then? I will have
               | a really bad time convincing my team mates, if that's the
               | case.
               | 
               | It's especially bad because, like any comment, it can say
               | one thing but the code may do something different
               | (actually happened to me).
        
               | xarope wrote:
               | it's a comment which can trigger an action (if you run
               | mypy).
               | 
               | So, unlike a comment, which does nothing, if you run mypy
               | and get some warnings, you can then do something about it
               | (whether it's just # type: ignore or you realise you made
               | a mistake with allocating to variable new_value versus
               | newvalue/new_valu/etc)
               | 
               | (btw, in case someone objects, some comments DO do
               | something, e.g. golang's godoc examples)
        
               | the_af wrote:
               | Now I'm confused because the root comment I was replying
               | to asserted that type hints are for documenting, not for
               | checking.
               | 
               | If they are for checking, then my other opinion stands:
               | that they are not very good at it (compared to my
               | experience with statically typed languages, even with
               | Typescript!).
        
               | zokier wrote:
               | yes, and yes. and they are still useful.
        
               | rglullis wrote:
               | You can have mypy doing the type _checking_. Just put it
               | on your CI pipeline alongside your tests.
        
               | the_af wrote:
               | I know because I tried setting it up. It's slow, requires
               | too much babysitting, and fails to catch cases.
               | 
               | In my experience, it just doesn't work cleanly out of the
               | box like in true statically typed languages, and so I get
               | pushback from my coworkers, who simply can't see the
               | point. And I can't blame them.
        
             | hoosieree wrote:
             | Just a couple hours ago, a student asked me what was the
             | type of a parameter in a function I wrote.
             | 
             | A type hint would have answered their question immediately
             | (as they were reading the code).
        
               | the_af wrote:
               | Yes, but _checked_ type annotations will do the same,
               | plus they are actually enforced.
               | 
               | An unenforced type hint is just like any comment: likely
               | to get out of sync with the code, and a human must do all
               | the work of keeping it up to date.
        
             | fluster wrote:
             | I view them as similar to python's "private" functions,
             | which are really just functions starting with an
             | underscore. The interpreter will let anyone call them like
             | any other function, but the general rule is don't do it,
             | unless you know what you're doing and are willing to deal
             | with the internals changing.
             | 
             | Python typing is like that. If I say a function takes a
             | List[int], but you know I'm just calling a for loop, you
             | can ignore it and hand me a Set[int]. Maybe it breaks some
             | day, but you're allowed to take that risk, if you have a
             | need.
             | 
             | Do either of these things do anything comments couldn't?
             | Not really. But they're ways of indicating intended
             | semantics without formally documenting your stuff, and when
             | most of what you use the language for is scripts, that's
             | actually pretty helpful. People actually use type hints in
             | a way they didn't with comments, and that's caused a major
             | improvement in code readability. Or at least that's been my
             | experience
             | 
             | You can absolutely look at all this and say python's a
             | crazy, terrible language you never want to touch, but if
             | you've got no choice on language for whatever reason, or
             | you're throwing something together and don't feel like
             | writing `private static final synchronized` forty time,
             | type hints are great.
        
               | giyanani wrote:
               | The typing (>= python 3.6?) and collections (>= python
               | 3.8?) packages have definitions for a bunch of protocols
               | (basically interfaces for structural typing).
               | 
               | So for that List[int] example, you probably want to take
               | a(n) Iterable[int], Iterator[int], or Collection[int]
               | instead, depending on exactly how you use it.
        
               | spoils19 wrote:
               | > don't feel like writing `private static final
               | synchronized` forty time, type hints are great.
               | 
               | We should think about whether there's a reason why we
               | want to be writing `private static final synchronized`
               | over and over again, after looking at the state of the
               | software engineer these days.
        
               | the_af wrote:
               | Thanks for your reply.
               | 
               | > _I view them as similar to python 's "private"
               | functions, which are really just functions starting with
               | an underscore_
               | 
               | Good analogy! I wish they were more like "private" class
               | methods, which are prefixed by a double underscore and
               | result in name-mangling: you can still access them from
               | outside if you want, but the code will really look ugly.
               | And you absolutely cannot access them accidentally.
               | 
               | Which is what type checking should be all about, right?
               | Preventing accidental misuse?
               | 
               | > _Python typing is like that. If I say a function takes
               | a List[int], but you know I 'm just calling a for loop,
               | you can ignore it and hand me a Set[int]. Maybe it breaks
               | some day, but you're allowed to take that risk, if you
               | have a need._
               | 
               | That's what drives me crazy. I come from the statically
               | typed world. This bit of Python's philosophy really
               | clashes with my world view. "These types are just
               | something someone wrote, they may or may not accurately
               | describe the code" seems so wasteful and unhelpful to
               | me...
        
             | rurp wrote:
             | They are useful for catching issue before code is committed
             | or deployed. At my work we run mypy as part of our test
             | suite, so failing type checks will block a merge or deploy.
        
               | the_af wrote:
               | How will they catch issues if they are not checked? The
               | comment I'm replying to insinuated type hinting is just
               | for documentation, and not necessarily meant to be
               | actually checked by the tooling.
               | 
               | You seem to be describing actual type _checking_ , which
               | I understand (though in my opinion, mypy is not a
               | satisfying tool for this).
        
             | gnulinux wrote:
             | It is good for programmers. Programmers think in many
             | different ways, but it seems to me that a sizable portion
             | of programmers think of code in terms types. Type hinting
             | makes it easy to convey type ideas. Where are we going from
             | which type.
             | 
             | I should say that anecdotally I find type hinting very
             | useful when I'm reviewing a PR from a part of the code I'm
             | not intensely familiar with.
        
               | minusf wrote:
               | when types are not checked and enforced, they get out of
               | date just like comments and docstrings.
               | 
               | i agree with the author, if the hints can't be trusted,
               | even just once, there's no point littering the code with
               | them, and are actually harmful when trying to debug
               | something using faulty hints.
               | 
               | i am a big fan of static typing but not in python. pick a
               | language that was designed around it. you can't make a
               | duck bark.
        
               | icedchai wrote:
               | For libraries, with many consumers of the code, type
               | hinting seems like a good thing. Many times I download a
               | third-party library and waste tons of time looking at
               | sample code. For application code (internal to the
               | service or whatever), it feels less valuable.
        
               | the_af wrote:
               | So a concise but not-legally-binding notation for types?
               | 
               | Useful, but way less useful than if it was actually
               | checked.
        
               | nine_zeros wrote:
               | Just put types in docstrings? Why type hinting with
               | imports and other dependencies, especially for complex
               | objects?
        
             | [deleted]
        
             | the__alchemist wrote:
             | The IDE catches type errors, and it lets you do things like
             | simulate structs using @dataclass.
        
               | Banana699 wrote:
               | @dataclass has nothing to do with the IDE in python, it's
               | a decorator, sugaring a higher order function.
        
               | the_af wrote:
               | I wish the tooling outside IDEs worked better. There's
               | obviously some magic going on with tools like PyCharm and
               | VSCode + plugins.
               | 
               | I wish this was the case with command line tools I can
               | plug into the build/deploy pipeline. I _know_ they exist,
               | it 's just they are unsatisfying and there are lots of
               | cases where they miss stuff that is trivial to catch in
               | statically typed languages.
        
               | nomel wrote:
               | As someone who lives in an IDE, I don't understand this.
               | Trying to get all of the functionality of the default
               | IDE, along with the trivially added plugins, to work in a
               | visually digestible and sane way would be a curses
               | nightmare of 30 command line tools. If you made it so
               | they played well together, where a human could interpret
               | what they were seeing, you would have something
               | indistinguishable from an IDE.
        
               | the_af wrote:
               | I find your opinion baffling to be honest.
               | 
               | It's simply not true. Every statically typed language
               | works like I described. Even Typescript works like this.
               | You can have your IDE plugins, but you definitely don't
               | need them to perform type checks. It's not true this
               | requires "a nightmare of 30 command line tools", you just
               | need one: the type checker (built into the language in
               | most statically typed languages, but sometimes split into
               | a separate tool).
               | 
               | Besides, your IDE doesn't live in the build pipeline (in
               | your CI/CD tool). So you cannot rely on it.
        
           | mirashii wrote:
           | I actually find that mypy is pretty weak and lacking, even
           | within the python ecosystem. pyright seems to do a much
           | better job at the type checking portion of things.
        
       | just-ok wrote:
       | Despite this:
       | 
       | > _Even if the Python runtime did check all the type hints at
       | runtime, then it would still be too late. I don't want a fancy
       | type exception at runtime. That already exists (most of the
       | time). I want to know about type mismatches in advance._
       | 
       | You should check out Typeguard [1], which lets you add a
       | @type_checked decorator to anything and get runtime type checking
       | that's far better than e.g. a random blowup when you split() on
       | an integer. It does introduce a significant amount of overhead,
       | but it's still useful during development alongside type hints to
       | avoid some of the pitfalls from this article.
       | 
       | In another vein, Any should definitely be used sparingly. For the
       | foo() function outlined in the article, Union[str, int] offers
       | more precision. In fact, you could even argue that using Any is a
       | code smell.
       | 
       | Overall, though, I agree with most of the sentiment in this
       | article. I find myself using type hints more as documentation
       | than anything else, since their true ability to prevent type-
       | related runtime bugs is very limited. Documentation has the same
       | qualms the author outlines, anyway:
       | 
       | > _You can not be sure that they are correct. [...] They waste
       | mental energy when reading code, they create new maintenance
       | burdens, and they are potentially deceiving: You cannot trust
       | them._
       | 
       | But they're still slightly better than docstrings...
       | 
       | [1]: https://typeguard.readthedocs.io/en/latest/userguide.html
        
         | riyadparvez wrote:
         | There's also bear-type for runtime type checking:
         | https://github.com/beartype/beartype.
        
           | pydry wrote:
           | I've been perplexed as to why this hasnt been built in to the
           | python runtime since day 1.
        
       | ZoomZoomZoom wrote:
       | > What I want is this: Some language that's as easy to use as
       | Python and it should be compiled and with good static typing...
       | 
       | Well, there's always Nim. [0]
       | 
       | > ...but it should also not be compiled because then it wouldn't
       | be as easy to use as Python anymore. Whoops?
       | 
       | Eh, there's Nimscript? [1]
       | 
       | 0. https://nim-lang.org/
       | 
       | 1. https://nim-lang.org/docs/nims.html
        
       | IshKebab wrote:
       | Yeah they're pretty bad but they _are_ still better than nothing.
       | If you are in the unfortunately position of having to use Python
       | I would recommend using them.
       | 
       | I would also strongly recommend using Pyright (the default
       | checker in VSCode) over MyPy. It's _so_ much better, and the
       | author is really responsive on Github.
       | 
       | But yeah, in general trying to use type hints in Python is like
       | trying to discuss philosophy in a mental asylum.
        
         | ActorNightly wrote:
         | The whole reason Python and JS surpassed most all other
         | languages is specifically because you can write code fast,
         | without worrying about strict definition of data structures.
         | 
         | The issues with python code bases aren't from a lack of strict
         | typing or type support, but from a lack of a good testing
         | framework.
        
       | [deleted]
        
       | LAC-Tech wrote:
       | _Did the mypy task in your build pipeline silently break?_
       | 
       | Haven't used python in years... you have build pipelines now?!
       | Why? Javascript refugees who can't shake their webpack stockholm
       | syndrome?
        
         | abalaji wrote:
         | I don't think the OP was referring to build pipelines, but
         | rather continuous integration pipelines. Build in the sense:
         | lint, install deps, and run tests.
        
       | raverbashing wrote:
       | Type hints work fine. They are _hints_ (that are checkable
       | through tools)
       | 
       | > But as a general rule: You don't know if there really is a tool
       | in place to check them.
       | 
       | Cool. So you just go and do stupid stuff if no one is looking?
       | 
       | Check it yourself. They're probably there for a reason. If you
       | think they're not needed, then sure, take them out.
       | 
       | > Most of this turned out to be wrong and it threw me off the
       | track during my debugging session.
       | 
       | Here's an idea: Then why don't _you_ fix it. If I see code that
       | 's wrong or bad, I go and fix it. It's your responsibility as
       | well
       | 
       | Now maybe try acting like they're anything but _type hints_ (and
       | I 'm _very glad_ Guido insisted it is optional and flexible - the
       | last thing the world needed is for Python to get consumed by Java
       | type checking pedantry where the compiler needs you to annotate
       | every single thing)
       | 
       | And every time I do something in Python that would be
       | "impossible" in Java I'm glad I'm not bound by the small-minded
       | type pedantry of Java.
        
         | wvenable wrote:
         | Can't you just type something as `object` in Java and make
         | anything possible?
        
           | raverbashing wrote:
           | It might be possible for some cases, yes. But not for
           | function pointers. And you don't get duck typing.
        
       | tsupiroti wrote:
       | I find it reasonable that Python doesn't enforce the type
       | checking. The owners of each project can choose how much to
       | enforce it and how.
       | 
       | Defining such style rules and validations is necessary with
       | almost every language. A codebase where developers are allowed to
       | use any C++ feature or browser API will become very messy as it
       | grows.
        
       | nickysielicki wrote:
       | Yes, they lack teeth. But what's the alternative?
       | 
       | * fork the language again? We just got out of Python2 hell.
       | 
       | * Docstrings, like we had before they were introduced?
       | 
       | They won't catch all bugs, but with minimal effort they'll catch
       | some bugs, and if you make an effort to really dig in, it'll
       | catch most bugs. To me, to accomplish that overnight on a
       | language with millions of existing lines, that's a big win.
        
         | wronglyprepaid wrote:
         | > Yes, they lack teeth. But what's the alternative?
         | 
         | In what way do they lack more teeth than Java with Object, Go
         | with interface{}, C++/C with void*?
        
       | MrJohz wrote:
       | As someone who's very used to Typescript, I find these complaints
       | very interesting, because they're often common for Typescript
       | newcomers as well. However, I think they - quite understandably -
       | misunderstand the purpose of these tools, and so get disappointed
       | when the tools don't do what they want or expect.
       | 
       | I think the traditional view of types is that they're about
       | declaring something to do with the memory layout of a particular
       | variable. Maybe not always directly, but I think most people have
       | this kind of intuition that an int is an int, a string is a
       | string, a struct is a struct (and a particular, explicit one at
       | that). In Java with subtyping, things get a bit more complex, but
       | it's usually fine.
       | 
       | That's generally not a good way to approach Typescript/mypy.
       | Typescript, for example, is absolutely unconcerned with whatever
       | value lives inside a particular variable. It's very possible in
       | Typescript to create types that can't even ever exist at runtime
       | (type brands are a good example of this). The compilation process
       | for Typescript is basically just stripping the types away as if
       | they were comments, and leaving the Javascript behind.
       | 
       | What Typescript _is_ is a slightly more complicated linter that
       | requires annotations. The types you put in are basically just
       | labels. When writing Typescript, your goal is to give every type
       | a label, and then run a program that tells you if all of those
       | labels are compatible with each other. If there is a label
       | mismatch (you 've used label "number" but you've done operation
       | "push" on it) then the linter will simply tell you you've done
       | something wrong. Moreover, these annotations can be very loose -
       | annotate something as `any` (or `Any` in Python) and the linter
       | will accept anything done to it. This means that you can always
       | break free of the linter and tell it that you know best (which is
       | true - it is probably impossible to statically validate whether a
       | given Javascript program will throw an error or not, so any
       | linter will have some cases where it prohibits a valid program -
       | the programmer requires the power to override the linter).
       | 
       | Viewing Typescript and mypy in this context helps a lot, I find.
       | It explains why casting doesn't throw runtime errors (a cast is
       | simply a lint annotation saying that a particular expression has
       | a particular label). It explains why JSON isn't validated when
       | it's parsed (you're just starting that the data has a particular
       | label/shape - it's up to you to ensure that that's true, but you
       | can do that check however you like, including not at all if
       | you're very confident in the quality of your data).
       | 
       | This raises the question about which process is better: one where
       | types get transformed into real data structures where all code is
       | kept valid at runtime, or one where the types act only as
       | assertions for a linter validating whether the code _ought_ to
       | remain valid. In my experience, a lot of it depends on how
       | valuable you find the dynamism in languages like Python and
       | JavaScript. If it 's very important for you, then traditional
       | typechecking approaches are probably not very viable because no
       | static type system can ever cover all correct Python programs.
       | However, levels plus a linter will resolve most programme
       | correctly, and still give the necessary overrides to allow for
       | other options.
       | 
       | So when it comes to the questions in the article, I think the
       | author would do a lot of good to approach Python type hints from
       | the perspective of a linter that requires annotations.
        
       | ciupicri wrote:
       | It reminds me of this 5 year old bug in mypy: "int is not a
       | Number?" [1].
       | 
       | [1]: https://github.com/python/mypy/issues/3186
        
         | benatkin wrote:
         | It isn't really one though (a lot of reading):
         | 
         | https://stackoverflow.com/questions/69334475/how-to-hint-at-...
         | 
         | I would rather my type checker give me the truth than gloss
         | over it. This issue should be kept open (it is) but they should
         | wait until a good solution is found that doesn't gloss over the
         | discrepancy.
        
       | NewEntryHN wrote:
       | TL;DR: type hints are a disappointment to me because they're only
       | hints.
        
       | POiNTx wrote:
       | Don't let perfect be the enemy of good. Type hints are usefull
       | especially in large codebases. I find myself using them with
       | minimal effort and they can catch bugs that otherwise wouldn't be
       | catched.
        
         | mindwok wrote:
         | Exactly. The article has some valid criticisms of the weirdness
         | of type hinting, but type hinting is a pretty large paradigm
         | shift added to a 20+ year old language. Yes it will have
         | shortcomings, but in my opinion has made working with large
         | Python codebases actually possible. It's a good thing.
        
       | flakiness wrote:
       | I use the type-annotated python at work and at hobby. I see the
       | point of OP, but I'd say it helps even if it's not perfect or
       | "sound".
       | 
       | Though I agree on its negative impact on the language ergonomics.
       | It removes the joy of writing "scripting language" and as a
       | statically typed language it is far from static-type-native ones.
       | 
       | Now I see it as a tax for compatibility: You enjoy dynamic typing
       | at the beginning of the project, but you have to pay it back once
       | you've grown up to a certain scale.
       | 
       | TypeScript to me feels much more like a native static typed
       | language because it is. Does it help to be a transpiler? Maybe.
       | But I would think that Hejlsberg just has done an astonishingly
       | good work to make it compelling. Python's type annotation is good
       | and completely reasonable, but gradual typing is such a hard
       | problem and being good is probably not enough here.
        
       | phailhaus wrote:
       | Python's type system _is_ a disappointment, but I don 't think
       | this article does a great job of explaining why. My biggest
       | gripes:
       | 
       | 1. There is no way to get typing like dataclasses without writing
       | your own mypy plugin. The syntax is simply not expressive enough
       | to do it. This means that if you want to be productive with a
       | library like Pydantic, you also have to add the mypy plugin to
       | your dependencies and add it to your mypy config. Otherwise, no
       | typing.
       | 
       | 2. You cannot compose types. There is no way to say "hey this
       | type is the same as this dictionary here, except the keys are all
       | optional." If you're trying to type a RESTful API, your only
       | option is to repeat yourself and carefully keep all your types in
       | sync.
       | 
       | 3. To this day, there is still no way to express optional keys.
       | Not "Optional" keys, but keys that can be left out of your
       | dictionary. The closest you can get is this weird hack where you
       | can set `total=False` in your TypedDict, which makes _all_ keys
       | optional.
       | 
       | I really wish Python learned from Typescript, but it's too late
       | at this point. Too many half-baked measures have already made it
       | into the spec.
        
       | jmugan wrote:
       | I love type hints. They make the code so much more readable. I
       | wish they could do more, but knowing what the programmer intended
       | for a variable is huge. Now, when I see code without type hints I
       | think, "Oh man, now I have to dig into everything to know what
       | anything is."
        
       | jonathan-adly wrote:
       | 100% agree - never really understood the movement behind adding
       | types to Python. Type hints are a useless complexity that yield
       | little return. If you want types, use something else other than
       | Python. The whole thesis behind Python is simple is better than
       | complex.
        
         | sirsinsalot wrote:
         | I find it best to see type hinting as "living documentation".
         | Yeah, you can ignore it, it is Python afterall, but if you want
         | the IDE/tools to have better more helpful hints ... use machine
         | readable hint documentation.
         | 
         | I'd argue if your functions are full of type-assert like
         | guards, _then_ use another language!
        
           | bb88 wrote:
           | I just saw someone on Twitter post a "IntegerType" class
           | which did exactly this, including capturing the sign --
           | because he couldn't trust int().
        
         | retrac wrote:
         | > useless complexity that yield little return
         | 
         | Typechecking allows certain errors to be detected at typecheck
         | time rather than at runtime. I don't personally consider that
         | useless. E.g. A mistake I just made. I'm working in a language
         | I don't know too well right now with strict static typing. The
         | file read function takes a handle. If I pass it a string of the
         | file name, rather than the handle result from file open, it
         | just doesn't compile. In most dynamic languages, that error
         | would not be detected until it executes.
        
         | mjr00 wrote:
         | How is "this function takes a string and returns a float" more
         | complex than "this function takes any data type and returns an
         | unspecified data type"?
        
         | Inityx wrote:
         | On the one hand yeah, I agree with this, but on the other hand
         | you have a lot of enormous software projects written in Python
         | that are decidedly not simple, and would be extremely difficult
         | to completely rewrite in a different language. Type hints do
         | offer some value in this circumstance, by making it easier for
         | disparate groups to modify the same large codebase though
         | static analysis.
        
         | bobbylarrybobby wrote:
         | They're great for autocomplete, but that's pretty much it
        
         | forrestthewoods wrote:
         | > If you want types, use something else other than Python.
         | 
         | Python is still strongly typed.
         | 
         | Me: what type does this argument need to be?
         | 
         | Python: you have to figure that out
         | 
         | Me: I just pass whatever I want?
         | 
         | Python: Oh no. Usually only a single specific type is
         | supported. But you have to guess what it is.
         | 
         | Me: what if I get it wrong?
         | 
         | Python: the program crashes at runtime
        
           | lifewallet_dev wrote:
           | You don't understand what "strongly typed" means... I give
           | you a hint, `"1" == 1` is a type error in Python but "okay"
           | in JavaScript because this one is "weakly typed", you're
           | confusing "dynamic typing vs static typing" with "strongly
           | typed vs weakly typed".
        
       | xarope wrote:
       | I'm surprised there's no mention of pydantic or other type
       | systems. I started with type hints, and find that the discipline
       | of using types invaluable, especially when coding public API
       | backends for which validation is a strong necessity, whether
       | semi-static (ala mypy) or runtime.
        
       | Lendal wrote:
       | I tried mypy when I first started into type checking in Python
       | back when I was trying to do Python in VS Code and I discovered
       | that mypy is a time-sucking anti-productivity disaster that needs
       | to die in a fire.
       | 
       | When I started learning PyCharm though, I discovered that type
       | checking can actually work well in Python and it is not a waste
       | of time at all. So I advise people now that unless you're using
       | PyCharm, do not waste any time on type checking Python. In which
       | case, have at it. I love it. PyCharm is really the only way to do
       | type-checking productively right now.
        
         | dgellow wrote:
         | If you use VSCode and Pylance (Microsoft python language
         | server) you don't need to setup Mypy, you can enable type
         | checking in user settings and it will use its own engine for
         | type analysis. You have two modes, basic and strict.
         | 
         | I would recommend to try out if you can, the experience is
         | quite good. I personally find "strict" too strict for the
         | current state of python, but "basic" is already very helpful.
         | 
         | The developer experience is still subpar when compared to
         | Typescript but it's improving fast (but I mean, typescript with
         | VSCode has one of the best developer experience I've ever
         | seen).
        
           | [deleted]
        
         | ainar-g wrote:
         | Could you elaborate on mypy? I'm not a Python developer (and I
         | really have much more experience with statically typed
         | languages), but if I ever had to maintain a Python codebase,
         | I'd assume that adding mypy and type annotations would be among
         | the first things I'd do, so it's a bit of a surprise to read
         | that.
        
           | kstrauser wrote:
           | I love mypy. It's fine, if sometimes a little alarming when
           | you aim it at a previously-untyped codebase. In my case, it
           | turned up plenty of type errors that _probably_ never became
           | a problem in production, but very well could 've. It's also a
           | nice thing to put in a CI pipeline to block new code errors.
        
       | pphysch wrote:
       | I agree treating Type Hints as comments is the way to go. It's a
       | bit nicer to use a library that is fully-hinted than one that is
       | not. But I don't worry about type-hinting my own code, unless
       | it's a particular complicated function signature that other
       | people will be calling.
        
       | chis wrote:
       | Only facts here. I think most large codebases eventually see type
       | hints drift away from reality as individual contributors are more
       | incentivized to hack in `Any` types to make things compile
       | instead of typing every line properly. This is especially common
       | for handling data objects which come in over the network - often
       | they can have a couple different types but people just type it as
       | one thing for simplicity.
       | 
       | Overall I do think type hints are worth it though, for maybe two
       | benefits. They force you to look at the ridiculous types you are
       | using, like `List[Union[None, str, List[Dict[str, str]]]]` which
       | is the sort of thing that happens in codebases all the time. It
       | adds just enough friction to push people to make explicit
       | dataclasses or simplify function returns, which is good. Secondly
       | they help with tracking functions which return None, which is a
       | pain when following callstacks in big codebases.
        
         | bb88 wrote:
         | My understanding was large python code bases (think Google)
         | have a large problem. Someone makes a code change and suddenly
         | it becomes difficult to find the scope of type errors in their
         | monorepo. That was the driving force IIRC.
         | 
         | That said, I think pytype makes a lot of sense since it infers
         | types from code, which you can edit by hand and then merge back
         | into the python file when your code is stable.
        
       | vesche wrote:
       | I agree. I'm glad that they're optional. One of the main reasons
       | to use Python is to prioritize development speed over performance
       | AND to prioritize read/write-ability over hand jamming mundane
       | syntax. I understand why some who have a background in typed
       | languages might prefer to use Python with type hints, but it
       | should be understood that they aren't very Pythonic.
        
         | ImprobableTruth wrote:
         | Man, the idea that type hints _reduce_ read-ability are crazy
         | to me. It 's like if someone told me that they think comments
         | make code less readable.
         | 
         | Like, even if you think that type hints have ugly syntax, prior
         | to them vast most projects just didn't bother with documenting
         | the shape of data, so you had to read source code, guess and
         | experiment. Unless you just don't care about knowing what
         | you're specifically working with (which strikes me as living on
         | the edge), how is it not an ergonomics gain?
        
         | forrestthewoods wrote:
         | > main reasons to use Python is to prioritize development speed
         | 
         | My experience with Python is that it slows development speed to
         | a crawl due to dynamic typing. It's maybe faster to write the
         | first 1000 lines. But after that it becomes slower and more
         | painful. At least in my experience.
        
         | mjr00 wrote:
         | > I understand why some who have a background in typed
         | languages might prefer to use Python with type hints, but it
         | should be understood that they aren't very Pythonic.
         | 
         | Completely disagree. The Python community has very rapidly
         | adapted mypy because of widespread recognition that yes, type
         | information is _extremely helpful_ for any code bases larger
         | than a few files and /or worked on by more than a few
         | developers. Every major Python library I can think of now has
         | mypy stubs available. If you're going to dismiss them as "not
         | Pythonic" you may as well dismiss anything other than Python
         | 2.7 as "not Pythonic".
        
       | s-y-s-y-s wrote:
       | I've annotated Python typing with a 20/80 approach. I annotate
       | strings, integers, floats, simple list and dict. I don't try to
       | produce complex type specs for lists, dicts, functions.
       | 
       | My company runs some kind of static analysis that checks things.
       | And I get 80% of the benefit with 20% of the work. So start
       | small, and don't expect perfection (yet).
        
       | wronglyprepaid wrote:
       | How is a grype with static typing that it is not enforced at
       | runtime? This comes up like once a week, have these people never
       | used statically typed languages?
       | 
       | > The fact that you can put nonsensical types wherever you want
       | and still get a working program has consequences.
       | 
       | Working is questionable, but nothing in C++ prevents this at
       | runtime either, nothing in JVM prevents this at runtime, static
       | typing is not runtime typing, it should not be, it is not the
       | USP.
       | 
       | > There is an Any type and it renders everything useless
       | 
       | Java has object, C++/C has void*, Go has interface{} - none of
       | these render the type system useless, and Python's type system
       | makes it a lot easier to write correct code than Go's type system
       | or C's type system.
        
       | nine_zeros wrote:
       | In my experience, people with less experience with object
       | oriented programming will end up creating lots of objects only to
       | create types. These objects have no business use case, nor do
       | they aid in any encapsulation. These objects are made just to
       | help typing. Nuts!
       | 
       | Python type hinting is like moving backwards in time because the
       | amount of time devs take to "hint", takes away the main reason
       | for using python, that is faster development. Might as well code
       | in Java at this point.
        
       | bb88 wrote:
       | > It feels really good to see a program compile without warnings
       | or errors. You then know that you got it right.
       | 
       | I don't know about that. So many C/C++ programs have core dumped
       | in my life and needed to be valgrinded to debug memory issues, or
       | went past the bounds of a pointer, or overwrote the stack, or...
       | whatever.
       | 
       | And you still don't get correctness without unit tests.
       | 
       | I'm not saying types aren't valuable, but they're not a crutch to
       | program correctness like people seem to think they are.
        
       | Animats wrote:
       | That's about what I said when the idea was first proposed. Actual
       | type declarations, both enforced and used to guide code
       | generation and optimization, would be fine.
       | 
       | Part of the problem is that, in the minds of many, Python ==
       | CPython. PyPy, which is a real compiler, is viewed as
       | "nonstandard". For PyPy, type information, although not in type
       | hint form, would be useful. But type hints, as currently defined,
       | are not. See the commentary on type hints at [1].
       | 
       | [1] https://doc.pypy.org/en/latest/faq.html
        
       | emacs28 wrote:
       | I find type hinting useful as an additional level of
       | documentation, especially for complex projects, and it helps my
       | future self understand my own code more quickly.
       | 
       | Also in my experience it can provide static analysis tools more
       | information and provide autocomplete suggestions in a wider range
       | of coding scenarios.
        
       | wardedVibe wrote:
       | They feel like someone told the Python dev team about Julia's
       | multiple dispatch based on types, and they felt like they had to
       | respond, even though they don't really provide the actual speed
       | and flexibility that motivates their use in Julia.
        
       | dataangel wrote:
       | Mypy checking is actually really good, and you can give it flags
       | to make it super strict. Setting it up in CI is the same work as
       | setting up any other linter. The only fault I had with it was 3rd
       | party libs not providing hints often enough.
        
       | smu3l wrote:
       | What is the precise definition of static typing? Both the article
       | and many comments in this thread refer to static typing or static
       | type hints in Python. But as I've always understood it, static
       | typing means that types are checked and enforced at compile time.
       | And if python is not compiled, the notion of static typing in
       | python does not make sense. So do I have it wrong? Or is the term
       | ambiguous?
        
         | ledauphin wrote:
         | static in this case can be understood to mean simply "prior to
         | (or separate from) runtime". In other words, it's based on what
         | you can check _without_ running the code.
         | 
         | It's worth noting that nearly every statically-typed language
         | currently in existence has either two separate "type systems" -
         | the static type system which is the formal type system offered
         | to the programmer, plus a runtime type system enforced, at
         | minimum, by the processor (e.g. you cannot divide by 0) that is
         | ultimately different from the static type system. The
         | 'question' in most cases is "how closely does the runtime type
         | system match the static type system?" In many if not most
         | languages, the answer is "not very".
        
           | tialaramex wrote:
           | > It's worth noting that nearly every statically-typed
           | language currently in existence has either two separate "type
           | systems"
           | 
           | Either that or... ? You should probably complete this
           | thought.
           | 
           | I don't think the distinction you've claimed make much sense,
           | but perhaps you had an alternative which you just never
           | explained.
        
       | ledauphin wrote:
       | this article is so full of... not-very-educated thoughts on
       | gradual typing in a dynamic language that it's hard to know where
       | to start.
       | 
       | A few concrete criticisms:
       | 
       | 1. If you're using a dynamic language, then _by definition_ the
       | language will not enforce your static hints at runtime. However,
       | good news! Python has always been strongly typed, and _does_
       | enforce types at runtime!
       | 
       | 2. A number of the examples given would be _impossible_ to
       | statically type in most compiled languages (those without
       | dependent types). It's hard to know where to go with a critique
       | saying that you can't fully represent heterogeneous values in a
       | dict, given that you can't do this _at all_ in many statically
       | compiled languages.
       | 
       | It seems to fall back on saying "use of the type system requires
       | too much discipline to be useful". This might be an interesting
       | criticism on its own; however many current users of Python can
       | say, from experience, that the required discipline is not a high
       | enough hurdle that it prevents us from using types consistently
       | and correctly.
       | 
       | There is plenty to critique about Python's static typing, but
       | this article would have been better titled "I'm confused about
       | Python's static type system and want somebody to show me how it's
       | actually used in real-world scenarios".
        
         | civilized wrote:
         | > not-very-educated thoughts on gradual typing
         | 
         | This seems like an inaccurate and condescending put-down. What
         | is the definition of "educated" in this context? Is there a
         | book or generally well-known resource?
         | 
         | The author is clearly thoughtful and curious. Near the top of
         | the post he says "what I'm hoping for is that someone will come
         | along and tell me that I got it all wrong. "When you do it as
         | follows, the system works: $explanation" Because, you know, I'd
         | really like to have static typing in Python."
         | 
         | > 1. If you're using a dynamic language, then _by definition_
         | the language will not enforce your static hints at runtime.
         | However, good news! Python has always been strongly typed, and
         | _does_ enforce types at runtime!
         | 
         | And yet, the author points out that this is a working program:
         | foo: int = 'hello'       print(foo)
         | 
         | In what reasonable sense can Python be said to "enforce types
         | at runtime" here?
        
           | ledauphin wrote:
           | This one is self-explanatory.
           | 
           | Can a string be printed? Yes! Then Python is (correctly)
           | allowing typesafe behavior here. Your (incorrect) annotation
           | does not in any way contradict the typesafe-ness of printing
           | a string (or an int). They're both equally printable.
           | 
           | This is just a very, very bad example, plain and simple. It
           | 'looks' bad to a superficial reading, but in practice it
           | demonstrates only what is already known about static typing
           | in Python - it is enforced (or not) separately from the
           | interpreter.
        
             | the_af wrote:
             | Agreed. Static typing is usually enforced during the
             | compile stage in other languages. It's specifically meant
             | to catch problems _before_ running the code (hence the
             | "static" in its name).
             | 
             | This said, I find the linting/type-hint-checking stage of
             | Python cumbersome and confusing :(
        
             | civilized wrote:
             | It seems that your point boils down to "Python enforces
             | types at runtime if you define 'enforce types at runtime'
             | not to include 'enforcing that data you declare to be of a
             | certain type actually is of that type'".
             | 
             | Am I the only one baffled by this way of thinking?
        
               | ledauphin wrote:
               | Python does and always has enforced types at runtime.
               | This is called duck-typing. If you're not familiar with
               | the concept of strong+dynamic, it is easy to see how this
               | could be confusing. This may help.
               | https://stackoverflow.com/questions/2351190/static-
               | dynamic-v...
               | 
               | Static type annotations by definition are not enforced at
               | runtime. This has been true of every language that has
               | ever used static typing, including C, C++, Java, Rust,
               | Typescript... you name it, statically typed languages
               | only enforce their static typing at compile/analysis
               | time.
               | 
               | Yes, it is possible to annotate types in Python
               | incorrectly. It's possible to do this in all other
               | languages that allow type-unsafe behavior (whether
               | natively or via reflection, etc). This may be less common
               | in some languages than in others, but it is fundamentally
               | possible in the vast majority of languages that perform
               | static typing, because those types are fundamentally
               | enforced at analysis time, not runtime.
               | 
               | The author of the article seems to be unfamiliar with
               | these distinctions, and maybe you are too. It's fair to
               | complain that these distinctions are confusing and make
               | things harder for programmers. Nevertheless, very few
               | languages have ever been designed with a type system that
               | acts exactly the same at analysis time and runtime. It's
               | a very difficult problem, partly because these are all
               | abstractions from the perspective of the underlying
               | computer, which only understands boolean logic and
               | integer/floating point math, and has virtually no other
               | notion of types in any formal sense.
               | 
               | Type systems are a complex topic, and as someone who has
               | been paying attention to them for a while, it's
               | frustrating to see uninformed discussion of them show up
               | on Hacker News. That said, it's perfectly understandable
               | that people are confused by these distinctions, and rest
               | assured there's a lot of effort going into developing
               | better languages that suffer _less_ from these issues.
               | 
               | For the everyday working programmer, however, there are
               | currently lots of tradeoffs to be made, and Python's
               | approach to static+dynamic typing is actually pretty
               | usable, all things considered, which is why the community
               | overall has embraced the new static typing despite its
               | blemishes.
        
               | the_af wrote:
               | > _Yes, it is possible to annotate types in Python
               | incorrectly. It 's possible to do this in all other
               | languages that allow type-unsafe behavior (whether
               | natively or via reflection, etc). This may be less common
               | in some languages than in others, but it is fundamentally
               | possible in the vast majority of languages that perform
               | static typing, because those types are fundamentally
               | enforced at analysis time, not runtime._
               | 
               | It is pretty damn hard to make this mistake in languages
               | that enforce static typing. I mean, you would have to go
               | out of your way to do so. In Python, however, it is
               | trivial to write the wrong type signature or to modify
               | the body of a function so that it no longer matches the
               | signature.
               | 
               | "Fundamentally possible but terribly unlikely, as opposed
               | to the Python way of doing it" would be a more accurate
               | description.
        
               | ledauphin wrote:
               | I think your (and the article's) argument could be
               | summarized as "static type annotations without automated
               | enforcement by actually running a type checker considered
               | harmful".
               | 
               | Since this argument is not meaningfully different from
               | "comments that are lies considered harmful", it seems
               | fair to expect reasonable people to dismiss it as
               | uninteresting.
        
               | the_af wrote:
               | > _it seems fair to expect reasonable people to dismiss
               | it as uninteresting._
               | 
               | Do you think that's a fair treatment of someone who
               | disagrees with you but has been respectful of your
               | opinion so far?
               | 
               | I realize proglang debates are flamewar territory. But I
               | have been very careful to state _I_ find Python type
               | hints puzzling and less useful than they should be. It is
               | obviously an _interesting_ opinion shared by many others,
               | not just me or the article 's author.
               | 
               | As a fan of statically typed languages, I do indeed find
               | some Python programmers engage in a form of Stockholm's
               | syndrome. It usually takes the form of the assertion "I
               | never found a bug that was a type error". Have you or
               | anyone you know ever said this?
               | 
               | In my mind, the opposite statement of the one you
               | attribute to me would be "wishful thinking and a positive
               | attitude is enough to catch mistakes, it's not necessary
               | to have help from automated tooling". In this day and
               | age, I cannot disagree _more_.
        
           | the_af wrote:
           | I agree with most of your comment, but I think there's a
           | miscommunication problem here.
           | 
           | When Python "enforces types at runtime" this is the actual
           | types, not type hints. Type hints are not a runtime artifact.
           | The "actual type" here is "string", and enforcing it means
           | Python would not allow invalid operations on it without
           | error'ing. A programming language that will let you do
           | basically anything to any value because it doesn't enforce
           | type safety is of course C. Python is safer than C.
        
             | AnimalMuppet wrote:
             | Yes and no. C will let you do things like:
             | *(unsigned long*)0xFFFFFF14 = 0x749235f8;
             | 
             | It will _not_ let you do things like:
             | *0xFFFFFF14 = 0x749235f8;
             | 
             | or                  char* s = "abc";        *(unsigned
             | long*)0xFFFFFF14 = s;
             | 
             | It also won't let you call thing.method without
             | thing.method _definitely_ existing.
             | 
             | Best of all, all of these are enforced at compile time.
             | 
             | Now, C absolutely will let you convert an int to a pointer,
             | or a char to an int, or an array to a pointer, or... well,
             | it will let you convert lots of things to lots of things.
             | Some of those things are unsafe unless you are quite sure
             | what you're doing.
             | 
             | > A programming language that will let you do basically
             | anything to any value because it doesn't enforce type
             | safety is of course C.
             | 
             | False on several grounds. You can't call something that
             | isn't a function. You can't call a function on something
             | that doesn't have it. You can't use an int as a pointer or
             | an array without casting it. You can't use an int as a dict
             | (not that C has any built-in idea of what a dict is...)
             | 
             | > Python is safer than C.
             | 
             | Depends on what you're doing, and what kinds of errors you
             | are more prone to.
        
               | the_af wrote:
               | I find this level of nitpicking puzzling.
               | 
               | You know what I meant and what error I was clarifying for
               | the comment I was replying to. Yet you went out of your
               | way to point all sorts of irrelevant mistakes in my post,
               | when the gist of it was right.
               | 
               | Do you feel it was it more important to correct me on
               | this trivial things, or was my reply more or less correct
               | when fixing the conceptual error in this sentence:
               | 
               | > _" In what reasonable sense can Python be said to
               | "enforce types at runtime" here?"_
               | 
               | Here's a nitpick of my own to your post:
               | 
               | > _" Some of those things are unsafe unless you are quite
               | sure what you're doing."_
               | 
               | Wrong. Type (un)safety does not depend on you "being
               | quite sure of what you're doing".
        
           | ImprobableTruth wrote:
           | I think the top comment was less polite than it should be,
           | but I would echo that the post seems to have a bit of a weird
           | understanding of gradual typing?
           | 
           | The Any type is to allow incremental typing. You start out
           | with dynamic code, and progressively 'typify' it by adding
           | more and more annotations, with Any working as a stopgap
           | where for the moment no valid type exists, until you finally
           | have a fully typed program. Inserting Anys because you're
           | lazy is like casting things to Object in Java because you're
           | lazy, abusing it like that is just incredibly sloppy and bad
           | code.
           | 
           | If someone is really struggling with this, simply use a
           | linting rule to ban Any in 'mature' code.
        
           | ungawatkt wrote:
           | For 1, there's some unfortunate but important semantics.
           | Python does not enforce type _Hints_ at runtime, as Hints are
           | in many ways fancy comments. But as pointed out, python is a
           | strongly typed language (at least on the sliding scale of
           | strong to weak), and types are known at runtime (call
           | `print(type(var))` to see them). And calling `1 + 'a'` will
           | result in a TypeError exception, unlike say JavaScript.
           | 
           | I believe this is the relavent passage in the article the GP
           | is referencing, which is incorrect if you take "runtime" to
           | mean something like when the line is executed: "Python is a
           | dynamically typed language. By definition, you don't know the
           | real types of variables at runtime."
           | 
           | It _is_ however correct to say you don't know the real type
           | _before_ runtime, at least python does not.
        
         | hermitdev wrote:
         | Personally, I took exception to the following from TFA:
         | 
         | > Python is a dynamically typed language. By definition, you
         | don't know the real types of variables at runtime. This is a
         | feature.
         | 
         | In "you don't know the real types of variables at runtime",
         | this is just flat wrong. One doesn't know the real type of a
         | variable _until_ runtime. It seems to me the author maybe has a
         | bit of confusion between weak typing and dynamic typing here.
        
         | the_af wrote:
         | I can only speak about my own experience:
         | 
         | Most people I know writing Python don't use type hints because
         | they are too much of a hurdle for very little payoff. The
         | tooling that pays attention to type hints is slow as molasses
         | or difficult to use or understand. The type hints themselves
         | are of dubious use.
         | 
         | As a fan and advocate of static typing, I find myself
         | advocating for type hints anyway, but I must agree I often
         | can't reply anything to my coworkers' objections, because
         | Python type hints are truly not that useful.
        
           | seti0Cha wrote:
           | Have you looked at the tools recently? LSP + Pyright is very
           | fast and plugins exist for many editors. Or maybe it's slow
           | on larger codebases or very large files? I don't have that
           | broad an experience yet, but so far it's been very good.
        
             | the_af wrote:
             | Sorry, I wasn't clear: I want command-line tooling for the
             | build pipeline, not for the IDE or any individual
             | developer.
        
               | ledauphin wrote:
               | mypy is quite fast at the command line. certainly fast
               | enough for CI usage, where speed is generally less
               | critical than in an IDE.
        
               | the_af wrote:
               | Not my experience!
        
           | wronglyprepaid wrote:
           | > The tooling that pays attention to type hints is slow as
           | molasses or difficult to use or understand.
           | 
           | I use mypy daily on big codebases, it is fine, not fast, but
           | fine.
           | 
           | > The type hints themselves are of dubious use.
           | 
           | They tell you when you make type errors, they help you
           | understand what type things should be. The same as in
           | literally every other language with static typing. There is
           | nothing special here, nothing different. python with a static
           | type checker running in strict mode is not fundementally
           | different from Java's static type checking.
           | 
           | > As a fan and advocate of static typing, I find myself
           | advocating for type hints anyway, but I must agree I often
           | can't reply anything to my coworkers' objections, because
           | Python type hints are truly not that useful.
           | 
           | What do they lack that would make them useful?
        
             | the_af wrote:
             | > The same as in literally every other language with static
             | typing
             | 
             | No, obviously not the same, otherwise I wouldn't be
             | complaining. They are not even on par with Typescript,
             | which I'm not a fan of either.
             | 
             | > [type hints] tell you when you make type errors
             | 
             | Not according to other comments I seem to be getting here.
             | Other people are arguing type _hints_ are not primarily for
             | _checking_ , but a form of notation for documentation.
             | Seems wasteful, and I wish the Python community and tooling
             | decided instead that they are for actually checking them.
             | 
             | > What do they lack that would make them useful?
             | 
             | Standardized, go-to tools that work in the build pipeline
             | and that catch most errors without taking a long time to do
             | so.
             | 
             | I haven't found mypy to fill these requirements. It's so
             | bad I cannot convince my coworkers to make the effort to
             | write more type hints.
        
               | wronglyprepaid wrote:
               | > No, obviously not the same, otherwise I wouldn't be
               | complaining.
               | 
               | What is the difference?
               | 
               | > They are not even on par with Typescript, which I'm not
               | a fan of either.
               | 
               | Go is not on par with Typescript or Python, I still don't
               | think it is okay for people to just say fuckit and
               | `interface{}` it all and it is still shit to work with
               | code that does use `interface{}`. At least Python with
               | mypy has null safety, something that Java and Go does not
               | have. There are some places it is worse than other
               | statically typed languages, others where it is better.
               | 
               | > Standardized, go-to tools that work in the build
               | pipeline and that catch most errors without taking a long
               | time to do so.
               | 
               | It is mypy. What actual type errors does mypy not catch
               | that you want it to catch? Why can't you use it in the
               | build pipeline? I do it every day, it catches all the
               | errors it should. The one complaint I can maybe see is
               | the duct type compatibility complaint, and it is not
               | really something that comes up that often for me, and
               | definitely not something I would say invalidates the
               | whole concept.
        
               | the_af wrote:
               | > _What is the difference?_
               | 
               | I'm not going to repeat myself, I already told you.
               | 
               | I find mypy slow, unsatisfying, inconsistent, and it
               | fails to catch many type errors. No, I'm not going to go
               | look in my work laptop to give you an example.
               | 
               | > _There are some places it is worse than other
               | statically typed languages, others where it is better._
               | 
               | In most places it is way worse, and I'll find it very
               | hard to find common ground with anyone who disagrees on
               | this.
               | 
               | Feel free to disagree, but I don't find this conversation
               | useful.
        
         | theodorejb wrote:
         | > 1. If you're using a dynamic language, then _by definition_
         | the language will not enforce your static hints at runtime.
         | 
         | Counterexample: PHP is a dynamic language which enforces static
         | type declarations at runtime.
        
           | ledauphin wrote:
           | Meh. you can do the same thing in Python if you really want -
           | there are dynamic interpreter shims that can do this.
           | 
           | The point is that it is not expected by definition, since by
           | definition, static != runtime.
        
         | zmgsabst wrote:
         | That's the point though:
         | 
         | Duck typing and heterogeneous dictionaries are (and have been)
         | standard Python.
         | 
         | Adding a type system which doesn't respect duck typing by
         | trying to access the member even when the types don't match or
         | which can't express standard idioms used in Python seems a poor
         | architectural choice.
         | 
         | It's not saying that Python's type system is "too much
         | discipline", but rather that the type system doesn't encode
         | typical Pythonisms.
        
           | ImprobableTruth wrote:
           | No offense, but have you actually given it a shot? Duck
           | typing is supported and you can get virtually all use cases
           | of heterogenous dictionaries by using union types and duck
           | typing. The article even touches on this.
           | 
           | edit: To be more precise: The article specifically mentions
           | that accessing invalid members give you a type error, but
           | posits that people will probably not bother and just use
           | 'any' instead. How is that not saying 'too much discipline'?
        
             | zmgsabst wrote:
             | Yep -- I use mixed annotations on my Python code because as
             | the person I'm responding to pointed out, they catch many
             | small type errors. Dataclasses have been awesome.
             | 
             | I'm also generally pro-types, but I think it's worth having
             | a discussion about this type system in the context of
             | Pythonisms.
             | 
             | - - - - -
             | 
             | If you're using "any" for most of your types, then it's not
             | providing value -- an untyped statement implicitly has the
             | type "any".
             | 
             | There's a reason I brought up the JSON example: loading and
             | manipulating JSON of varying structure is something I do _a
             | lot_ at work.
        
           | Znafon wrote:
           | Python typing supports duck typing:
           | https://peps.python.org/pep-0544/
           | 
           | and heterogeneously typed ducts:
           | https://peps.python.org/pep-0589/
        
             | Spivak wrote:
             | And you can make it work at runtime too! So as long as you
             | have the right methods and attrs isinstance on your duck-
             | typed object will return true!
        
             | zmgsabst wrote:
             | I read 0544 and the proposal for protocols fails to support
             | the main benefit of duck typing, as it requires the
             | substituted-for class to be defined as a protocol.
             | 
             | Traditionally, duck typing is used to inject types into a
             | library that isn't expecting extension at that particular
             | point -- eg, substituting a test class for a real class in
             | a data object that normally wouldn't be a protocol.
             | 
             | I'm not seeing how that PEP addresses that use case.
             | 
             | - - - -
             | 
             | Similarly, the heading on the dictionary says "for a fixed
             | set of keys" -- but what if I want a dynamic heterodox
             | dict? Eg, unpacking JSON.
             | 
             | You just end up shoving "any" all over the place. At which
             | point, are the types helping?
             | 
             | Though, protocols do help the dict case for typing:
             | 
             | dict : Hashable -> Any
        
               | ljojiasdf wrote:
               | Can you re-read please?
               | 
               | https://peps.python.org/pep-0544/#:~:text=Structural%20su
               | bty....
               | 
               | > substituted-for class to be defined as a protocol.
               | 
               | ... which is false
               | 
               | > Similarly, the heading on the dictionary says "for a
               | fixed set of keys" -- but what if I want a dynamic
               | heterodox dict? Eg, unpacking JSON.
               | 
               | You can quite obviously decode to recursive types (e.g.
               | using pydantic), not sure what the problem is.
        
               | zmgsabst wrote:
               | Your link appears not to work (for me) -- can you cite
               | what you believe I have incorrect?
               | 
               | This section seems to agree with me, where it explains
               | why normal classes can't be subclassed to protocols:
               | 
               | > Now, C is a subtype of Proto, and Proto is a subtype of
               | Base. But C cannot be a subtype of Base (since the latter
               | is not a protocol). This situation would be really weird.
               | In addition, there is an ambiguity about whether
               | attributes of Base should become protocol members of
               | Proto.
               | 
               | https://peps.python.org/pep-0544/#protocols-subclassing-
               | norm...
               | 
               | - - - -
               | 
               | I'm not sure why you think it's "obvious" that you can
               | use a third party library to solve the problem -- or why
               | that addresses my complaint that the built-in type system
               | doesn't work for that.
               | 
               | If anything, the existence of a third party library hints
               | the standard library doesn't cover the use case.
        
         | dtech wrote:
         | It seems to me like Python needs to get Typescript's
         | capabilities (if Python wants to go further this way of
         | course). It solves all these problems very well, and has no
         | problem with 2 and most of the author's objections.
        
           | ledauphin wrote:
           | Typescript does absolutely fantastic type inference, which
           | mypy definitely does not. I think that's a huge advantage for
           | Typescript over mypy, and it's really foundational to the
           | value it provides.
           | 
           | However, even in Typescript it is nontrivial to _annotate_
           | these complex types, and in most cases it's still possible to
           | do in Python - you just need to commit to using something
           | like dataclasses rather than pretending that what you have is
           | a `dict`.
           | 
           | Basically, to get the most out of static typing in the world
           | of Python, you do have to write more boilerplate than you
           | would in Typescript, and in particular you need to avoid
           | dicts and prefer various sorts of class-based data containers
           | (again, dataclasses, attrs, namedtuples, etc).
        
         | cardanome wrote:
         | > 1. If you're using a dynamic language, then _by definition_
         | the language will not enforce your static hints at runtime.
         | However, good news! Python has always been strongly typed, and
         | _does_ enforce types at runtime!
         | 
         | So PHP is not a dynamically typed programming language
         | according to you? It enforces type hints at runtime just fine.
         | 
         | There is nothing in the definition of dynamically typed
         | languages that says they can't use type hints to perform
         | runtime checks.
        
       | albertzeyer wrote:
       | > Just the type hints were wrong.
       | 
       | > warnings of IDEs are simple to ignore
       | 
       | This is unusual. In my experience, of codebases I have worked
       | with or have seen, when there are type hints, there are almost
       | all perfectly correct.
       | 
       | Also, you can setup the CI to check also for IDE warnings. For
       | example, we use this script for PyCharm:
       | https://github.com/rwth-i6/returnn/blob/master/tests/pycharm...
       | 
       | The test for PyCharm inspections only passes when there are no
       | warnings.
       | 
       | Although, I have to admit, we explicitly exclude type warnings
       | because here we have a couple of false positives. So in this
       | respect, it actually agrees with the article.
       | 
       | But then we also do code review and there we are strict about
       | having it all correct.
       | 
       | Yes, I see the argument of the article that the typing in Python
       | is not perfect and you can easily fool it if you want, so you
       | cannot 100% trust the types. But given good standard practice, it
       | will only rarely happen that the type is not as expected and
       | typing helps a lot. And IDE type warnings, or mypy checks still
       | are useful tools and catch bugs for you, just not maybe 100% of
       | all typing bugs but still maybe 80% of them or so.
       | 
       | > Isn't it better to detect at least some errors than to detect
       | none at all?
       | 
       | > You can not be sure that they are correct. As such, you must
       | always treat them as if they were wrong.
       | 
       | I don't get this argument. Isn't this the case for all other code
       | as well? Most code has not been formally verified to work 100%
       | correct. So you assume always all code is wrong? This doesn't
       | make sense.
       | 
       | > They [type hints] waste mental energy when reading code
       | 
       | How? The author even acknowledges that you could just treat them
       | as code comments if you like. By that argument, all code comments
       | waste mental energy?
        
         | throwaway81523 wrote:
         | > I don't get this argument. Isn't this the case for all other
         | code as well? Most code has not been formally verified to work
         | 100% correct. So you assume always all code is wrong? This
         | doesn't make sense.
         | 
         | It isn't that you have to assume the code is wrong (you always
         | have to assume that code is wrong). It's that even though you
         | write type hints and they pass mypy, you still have to assume
         | that the code has type errors. That is, mypy doesn't rigorously
         | check that the program's types match its annotations. It only
         | approximately checks that.
         | 
         | In (some) other languages, the type checker is 100% sound, so
         | if your program passes type checking, you can be completely
         | sure that the types all match. Opportunities for the code to be
         | wrong are thus limited to mismatches between the types and the
         | desired behaviour.
        
       | rurp wrote:
       | After working in Python without type hinting for quite some time
       | before joining a team that uses it heavily, I was pretty
       | skeptical about how useful it would be give the many rough edges
       | I had read about. After using both approaches for a while I think
       | that type hints are both very flawed and surprisingly useful.
       | 
       | Yes MyPy and type hinting in general has many limitations, rough
       | edges, and occasionally baffling behavior. Despite all that, I
       | think it is helpful for pretty much any Python project. Type
       | hinting does catch a lot of potential issues and the syntax is
       | very simple. I tend to fill in the types even on a first pass at
       | some code since they help so much in tracking various
       | interactions.
       | 
       | I think the bottom line is that something doesn't have to be
       | great in order to be useful.
        
       | Humphrey wrote:
       | While I love the idea behind Python's type hints, they are merely
       | a shadow of the success of TypeScript.
       | 
       | Like the author, I've mostly given up on adding type hints in my
       | Python code. I now only use them when I want to help my IDE find
       | autocomplete suggestions.
       | 
       | Whereas TypeScript was a game changer for JavaScript. I used to
       | hate JavaScript, but somehow TypeScript has become one of my
       | favourite languages! How has the advent of Typing has changed my
       | opinion on these two very similar languages?
       | 
       | - JavaScript without types is a mess, whereas Python
       | comparatively was much better, esp since it does runtime duck
       | type checks.
       | 
       | - Python type hints are much similar to Flow type hints in JS,
       | which I tried, but ditched for the same reasons as Python type
       | hints.
       | 
       | - I was hesitant to try TS's all in approach, cause it was harder
       | to introduce into a project, but after having converted a number
       | of projects to TS, I can see that going all-in is a much better
       | approach than just adding hints as you go.
       | 
       | - TS does checks at many more levels. Eg, if a property is
       | optional or could have different types, it is a syntax error if I
       | don't check the value is valid before use.
       | 
       | - TS does an amazing job of auto-detecting types, so most of the
       | time you don't need to specify types, and it enforces these just
       | as if you declared them.
       | 
       | - TS has reached the critical mass were most popular packages now
       | include type definitions, I very rarely have to add @types/*
       | anymore. This means you get full intelisense on all 3rd packages!
       | I spend a lot less time referring to documentation now!
       | 
       | In hindsight, compiling out types is a great work flow.
       | TypeScript is so good that it has made me enjoy Python less. If
       | there was ever a Python equivalent to TS which reached a critical
       | mass of support, I'd jump all-in in a heartbeat.
        
         | Frotag wrote:
         | This is exactly my experience. I've also found that Python's
         | type annotations for even basic stuff like are way clunkier to
         | write.
         | 
         | For example an optional requires a typing.Optional import or a
         | an ugly "| None" instead of a question mark like TS has. And
         | good luck trying to annotate some complex / nested json, you'll
         | need a bazillion intermediary classes.
        
       | galdosdi wrote:
       | I haven't used python's type hints much yet but I used TypeScript
       | a bunch about a year ago and I have the exact same complaints.
       | 
       | Most of the benefit of types goes away unless _everything_ is
       | typed... my libraries, the libraries my libraries use, etc. I
       | should be able to jump around in and out of library code
       | following types and usages thereof in my IDE, making conclusions
       | that are accurate based on what the types say.
       | 
       | When some of your libraries (or indirect dependencies) don't have
       | types, you can no longer ever make any firm conclusions when
       | exploring a complex codebase based on types. I want to change a
       | method in the Widget type, and my IDE says it's used in 4 places.
       | But in reality, that just means 4 or more places, who knows if
       | there are others.
       | 
       | Adding types to a language that doesn't already have them is very
       | hard for this reason. Until many years pass and they're in
       | universal use, they add little value.
        
         | [deleted]
        
       ___________________________________________________________________
       (page generated 2022-04-21 23:02 UTC)