[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)