27 ms·
Python’s “type hints” are a bit of a disappointment to me
- ciupicri 5y agoIt reminds me of this 5 year old bug in mypy: "int is not a Number?" [1]. [1]: https://github.com/python/mypy/issues/3186 https://github.com/python/mypy/issues/3186
- benatkin 5y agoIt isn't really one though (a lot of reading): https://stackoverflow.com/questions/69334475/how-to-hint-at-number-types-i-e-subclasses-of-number-not-numbers-themselv/69383462#69383462 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.
- xarope 5y agoI'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.
- POiNTx 5y agoDon'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 5y agoExactly. 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.
- goodoldneon 5y agoTotally agree. Mypy isn't perfect but it's so much better than no type annotations
- markus_zhang 5y agoI'm using it sparsely. But how do I use it for external lib? Sometimes it's kinda difficult to know what exactly the type is.
- faangiq 5y agoPython type hints plus vscode is like god mode.
- xvmodvx 5y agoI'm sorry, but I'm writing this response without reading all the previous comments, but with almost 600 directly to it and more comments to a comment I hope it's understandable. However I did read a good portion of them and I'm confused...I thought Python doesn't use types everything is an object according to their documentation. Now for my 2 cents, if you don't care, don't read it... a lot of the comments aren't based on facts but opinions and a lack of understanding of the actual language, funny that I write that after my previous sentence huh? :) . Every language has goods and bads, don't think as someone who as a Python programmer or C programmer, just a programmer and use the best tool for the task you're trying to complete. If you've been programming for awhile you should have used a dozen different languages at some point. Don't focus on what the language can do but understanding the underlying concepts and then you can easily use the one that makes the most sense for that project.
- galdosdi 5y agoI 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 5y ago[deleted]
- Loeffelmann 5y agoI think Typescript nowadays has reached critical mass where most packages at least have a @types/* definition. I can't remember the last time I had to use a package that didn't provide types. I had the types be wrong one time though.
- deleted 5y ago[deleted]
- flakiness 5y agoI 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.
- jmugan 5y agoI 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."
- mountainriver 5y agoYeah this is such a huge benefit that’s rarely discussed. It wildly increases the understanding of a code base which makes developers more productive and safe
- vermarish 5y agoYeah. I usually don't bother with type hints for local variables, but for parameters and return types, it makes skimming old code so much easier.
- jonathan-adly 5y ago100% 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.
- mjr00 5y agoHow 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 5y agoOn 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 5y agoThey're great for autocomplete, but that's pretty much it
- forrestthewoods 5y ago> 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 5y agoYou 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".
- Lendal 5y agoI 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 5y agoIf 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 5y ago[deleted]
- ainar-g 5y agoCould 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 5y agoI 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 5y agoI 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 5y agoOnly 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 5y agoMy 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.
- mountainriver 5y agoYup this is the biggest benefit. Working on a large untyped code base is about as bad as it gets
- goodoldneon 5y agoYou can disallow `Any` with the `--disallow-any-explicit` option
- vesche 5y agoI 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.
- forrestthewoods 5y ago> 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 5y ago> 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".
- ImprobableTruth 5y agoMan, 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?
- goodoldneon 5y agoCode is way less readable without types. If I see this: def create_user(user): other_function(user) Then how do I know what `user` is? Is it a dictionary? An object? If it's an object, where's its class definition? To find the answer I need to search for all the code that calls `create_user`, and then code that calls that code, and then code that calls that code, ad nauseam. Onboarding into a huge, untyped codebase is brutal
- s-y-s-y-s 5y agoI'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).
- emacs28 5y agoI 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 5y agoThey 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.
- ledauphin 5y agothis 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".
- moonchild 5y ago> If you're using a dynamic language, then _by definition_ the language will not enforce your static hints at runtime What definition is that? Raku is a dynamically language with gradual typing which will enforce those types at runtime (if it cannot do so at compile time).
- Matheus28 5y ago> you can't do this _at all_ in many statically compiled languages What statically compiled language doesn't provide a way (sometimes clunky) to have heterogeneous values in a dict? You can do that with void* in C, even
- dtech 5y agoIt 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.
- daenz 5y agoOpinions 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.
- davidhariri 5y agoFully 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 5y agoMy 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/ https://pypi.org/project/typeguard/
- throwaway81523 5y agoI'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 5y agoSame 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.
- just-ok 5y agoDespite 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 https://typeguard.readthedocs.io/en/latest/userguide.html
- riyadparvez 5y agoThere's also bear-type for runtime type checking: https://github.com/beartype/beartype https://github.com/beartype/beartype.
- pydry 5y agoI've been perplexed as to why this hasnt been built in to the python runtime since day 1.
- bayesian_horse 5y agoPython was first released in 1991.
- 5y ago
- IshKebab 5y agoYeah 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 5y agoThe 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.
- IshKebab 5y agoJS is popular because it's literally the only language web browsers support. Python is popular because it's very beginner oriented, so it's the first language a lot of people learn. It's modern BASIC. Neither of those things mean that writing dynamically typed code is a good idea. The idea that you can write dynamically typed code faster isn't even true once you get past a couple of hundred lines.
- ActorNightly 5y agoThis concept of "programer is generally dumb, so languages must have features to prevent them from making mistakes", with strong typing falling under those features, is solely an academic exercise that is taught in academia, and perpetuated by people who just wanna fit the mold in FAANG and other big players. And Python being popular because its basic/beginner oriented is a laughable statement. http://highscalability.com/blog/2012/3/26/7-years-of-youtube-scalability-lessons-in-30-minutes.html http://highscalability.com/blog/2012/3/26/7-years-of-youtube.... Not to mention that all the bleeding edge ML stuff is Python first. Language adoption directly depends on how quickly people can build stuff in that language, and its an exponential effect, because with speed of development comes more libraries, which in turn allows other people to build stuff that uses those libraries quicker. And the initial speed of development directly depends on the programmer having to manage less things. Static typing, in real world, is often a hinderance because code bases are dynamic, and having to go and refactor code because data definition changed takes time. And if you have competent programmers that write clean code and a good code review and testing framework, static typing gives you no advantage since the time spent fixing issues due to failing tests will be equivalent to spending time fixing issues with failure to compile.
- raverbashing 5y agoType 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 5y agoCan't you just type something as `object` in Java and make anything possible?
- raverbashing 5y agoIt might be possible for some cases, yes. But not for function pointers. And you don't get duck typing.
- tsupiroti 5y agoI 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 5y agoYes, 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 5y ago> 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*?
- reikonomusha 5y agoIdiomatic C and Go programs aren't labeling everything with those types, and the language implementation enforces those types at compile time. Since types are optional in Python, it's necessarily true that an "Any"-like type is prioritized since it's the default. Moreover, cpython doesn't check anything when it bytecode-compiles. Any-by-default and no-built-in-checking feels pretty defanged to me.
- wronglyprepaid 5y ago> Since types are optional in Python, it's necessarily true that an "Any"-like type is prioritized since it's the default. Moreover, cpython doesn't check anything when it bytecode-compiles. mypy is pretty whiny about types, and sure, if you add Any everywhere then you have just defeated the type checker, but this is no different from putting interface{} everywhere for Go. > Any-by-default and no-built-in-checking feels pretty defanged to me. Is running mypy on the code base that much to ask?
- NewEntryHN 5y agoTL;DR: type hints are a disappointment to me because they're only hints.
- nine_zeros 5y agoIn 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.
- noitpmeder 5y agoThis has to be a troll comment. The overhead of typing is literally _nothing_ compared to the amount of time it takes to sift through code to figure out a) what types a function/class accepts as arguments and b) what types are returned. If you don't check it then I agree it's useless. However, working with libraries that are typed is an _insane_ productivity boost over working with untyped libraries.
- ReflectedImage 5y agoTyping in Python is generally a code smell. Typing encourages a large number of bad coding practices. If you can apply typing to a Python program then you are not taking advantage of the dynamic nature of the language to write simpler and shorter code. In Python world, unit tests cover what is normally handled by typing.
- kortex 5y agoWhat. > Typing encourages a large number of bad coding practices. I'm sorry, what? What exactly is the bad practice here? Not passing random dicts to my coworkers only to surprise them because the key was userid and not user_id? Or wasting time bugging an overworked dev to ask what their crazy 8 levels of dynamic indirection magic are doing, vs just being able to Cmd-B and step through the code path? > If you can apply typing to a Python program then you are not taking advantage of the dynamic nature of the language to write simpler and shorter code. Yeah, no, flat out wrong. You can use typing with dynamicism to do magical things. FastApi works a near miracle, generating serializers, deserializers, openapi docs, automatic api deprecation warnings, not to mention type safety. Properly typed python is faster to write and safely magical.
- bb88 5y ago> 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.
- albertzeyer 5y ago> 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-inspect.py 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 5y ago> 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.
- ZoomZoomZoom 5y ago> 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/ https://nim-lang.org/ 1. https://nim-lang.org/docs/nims.html https://nim-lang.org/docs/nims.html
- PMunch 5y agoNot sure what the compiled != easy to use bit comes from anyways. If anything I'd say that part of Nim makes it easier to use, I don't have to worry about whether or not the target has Python installed.
- MrJohz 5y agoAs 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.
- phailhaus 5y agoPython'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.
- kirbyfan64sos 5y ago> 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. This would be solved by PEP 681, which originates from (and is already used in) pyright: https://peps.python.org/pep-0681/ https://peps.python.org/pep-0681/ > 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. This is solved by PEP 655, which introduces NotRequired: https://peps.python.org/pep-0655/ https://peps.python.org/pep-0655/ It's implemented in mypy 0.930: https://mypy-lang.blogspot.com/2021/12/mypy-0930-released.html https://mypy-lang.blogspot.com/2021/12/mypy-0930-released.ht... > I really wish Python learned from Typescript, but it's too late at this point Personally, I feel like it's partly just entirely different styles: Python relies on a mix of nominal and duck types, whereas JavaScript is much more focused on structural typing. As a result, there are a lot of things like TypedDict that are absolutely essential for JS to even function but a decent bit less so in idiomatic Python code (keeping a significant amount of dicts around uses much more memory than objects, I recall a PyCon talk explicitly mentioning this too).
- wronglyprepaid 5y agoHow 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.
- shultays 5y agoDifference between any and object, void* and interface{} is you can't really do anything with the second. Sure you can store something on an "object" type but you need to cast it back to do anything which discourages usage of it (and add runtime checks, usually) While in python you can mark something as "any" and continue using it as is.
- dataangel 5y agoMypy 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 5y agoWhat 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 5y agostatic 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 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 5y ago> 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 5y agothat was a typo - no "either" was intended. I've amended the original. not sure if that will help clarify?
- reikonomusha 5y agoPython is compiled, just not to machine code.
- LAC-Tech 5y agoDid 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 5y agoI 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.
- rurp 5y agoAfter 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 5y agoWhile 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.
- hannofcart 5y agoTo be fair, you're comparing a static typed language that transpiles to JS with a type annotation system for a dynamic lang. Pylint is closer to Flow than Typescript.
- Humphrey 5y agoOh of cause -- and I suspect TS only became so good because it had the freedom to be a new language.
- Frotag 5y ago
- Animats 5y agoThat'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 https://doc.pypy.org/en/latest/faq.html
- simonw 5y ago"You don’t know if there really is a tool in place to check them." Every project I interact with that uses type hints runs mypy as part of CI - and I can see that they're setup to do that by looking at the CI configuration (which these days is usually done using GitHub Actions). I wouldn't add type hints to a project without also configuring mypy for it.
- sevensor 5y agoPrecisely. We don't merge unless the result passes mypy.
- Bedon292 5y agoWe use pre-commit and you can't even commit until it passes mypy. It can be a bit frustrating sometimes, but overall it has saved us from a lot of issues.
- folkrav 5y agoI like the validation scripts being available in a repo so I can run them locally before pushing to CI, but I also often use WIP commits and quick fixups and then rebase before opening the PR, so pre-commit hooks are really annoying to my workflow. I more often than not just do `git commit --no-verify` or simply delete the git hook in `.git`, then just run it myself before pushing. Anyway CI will catch it, so I don't see much value in forcing it on individual machines.
- ohmahjong 5y agoThis has been my experience as well, as someone who added a pre-commit hook (black and mypy) to a repo in lieu of adding it to CI (it was a while ago). I came back to the team a year later to find that everyone had simply disabled the hook, and forgone typing/formatting entirely. A day or two of fixing formatting, type hints and linting errors later, the CI pipeline had a new step enforcing all three :)
- gorgoiler 5y agoI never liked how go makes you fix all your types before letting you run a program. Suppose I wanted to hack something up and run it, just as a new idea? Maybe change a library function that is called in 20 places, but I only want to test it in one call site. Nope! Go forces you to polish up your turd of an idea in all 20 call sites before you can see that your algorithm / model / refactoring is nonsense. If you back out of the idea then all that turd polishing was a waste of time. The mypy-python workflow, on the other hand, lets me write my nonsense, see that it was a bad idea, then throw it away without eating up more time than I needed to with satisfying all the type checking ceremonial stuff. Much nicer. It’s a linter that follows the “make it work, then make it right, then make it fast” iterative workflow that I’m used to. Alas, I suppose if I wasn’t an imposter in the programming world, I would be able to dream up my changes and think them through in my head properly before committing them to my text editor. Maybe I wouldn’t even need to do that because my ideas are just great all the time instead of 50/50 between ok and terrible. I’m not smart like that, and it felt like go went out of its way to rub it in. Maybe I used go wrong. I haven’t touched it in a decade. Is there a “hey ho your types are all out of sync but let’s try and compile anyway” option?
- valcron1000 5y agoThe only compiled language that I know that supports this kind of development is Haskell by enabling '-fdefer-type-errors'
- lolinder 5y agoThere's a big difference between Python's types and and Go's: in Python they're only there to check correctness while in Go they're there to tell the compiler how to lay out the machine code. If the compiler ignored types in Go it wouldn't just throw an error message at runtime, the behavior would be completely undefined.
- gorgoiler 5y agoThat’s interesting. The hacky-developer option I’m after is the ability to cull pieces of code if they do not type check, I guess.
- ironman1478 5y agoThis article has a really strange tone. For example, there is this section "There is an Any type and it renders everything useless". Yeah, so does C with (void*). Just because somebody is abusing a tool doesn't mean the tool is wrong. Any is valid with dealing with a dictionary type that is deserialized from some file. If somebody is just injecting Any into their code because they don't know what they are doing, educate them. The takeaway that type hints are worse than doing nothing just doesn't comport with my experience where the type hinting has caught very legitimate subtle bugs one code that was infrequently used. I wonder if the author would make the same argument for TSAN, UBSAN, or ASAN? Coverity? Or other annotation systems that help outside of the compiler? These tools are godsends, but do have false positives if their scope is understood.
- awinter-py 5y agopossibly orthogonal, but fastapi's use of type hints to parse params + payloads for REST is life-changing with the exception of some edgy form / upload issues, it's been bulletproof for me fastapi feels like something the universe wanted to exist and type hints are a natural DSL for it
- sevensor 5y agoThe way to think about gradual type annotations is not like types in C. You're not saying "this variable is 8 bytes that we're going to interpret as a floating point number." What they do is let you express constraints on the behavior of your program, and then run another program to check whether those constraints have been violated. Suppose you start with the function def foo(bar, baz): if bar > baz > 0: return bar / baz return "bar is not bigger" And this is what you want the function to do, for some reason. But by the time you start writing other code, you've forgotten about the unusual "bar is not bigger" case, and you just assume you're always getting a number back. This could turn into a runtime exception somewhere else in your code because a field in some object somewhere now has a value of the wrong type, but you've never run into it so you don't know about the ticking time bomb. Now you start adding type annotations to foo: def foo(bar: float, baz: float) -> float: ... And when you check the types, mypy yells at you, and you realize you actually need to write this: def foo(bar: float, baz: float) -> Union[float, str]: ... At this point mypy starts informing you about all the places you failed to handle the "bar is bigger" return value, and you go and fix them. You keep going until all of the constraints you've put on your code are consistent. You don't have to completely type everything for this to be useful, nor is it particularly important to check this stuff at runtime, because all mypy is doing is telling you that the code you've written satisfies the assumptions you're telling it about.
- ModernMech 5y agoThis is the kind of thing that happens when a language that used to be niche starts gaining more widespread use. People from other languages come along and want the niceties they enjoy to exist in the new language they are learning. The same thing happened to JavaScript; it used to just be a browser language for running scripts, and then it turned into a server side language with a module system and everything else. There were a lot of growing pains involved in that transition. Now people who use other languages are coming to Python and thinking "Wouldn't it be great if..." and that's how Python the language is going to evolve. But we're going to have to go through this interim phase of awkward adolescence before type annotations mature as a feature.
- czardoz 5y agoThis article captures a lot of the rationale behind why we're building Static Python within Cinder: https://github.com/facebookincubator/cinder#static-python https://github.com/facebookincubator/cinder#static-python
- linsomniac 5y agoHonestly, I've recently written a few 300-500 line programs in Python using type hints and I'm never going back. And I'm not even using mypy often, if ever. My editor now has a fairly deep understanding of my code, and can tell me of all sorts of surprising errors I'm making before I run the code. There have been a few times where I found an error, went into the editor and saw I had missed a error message about that line. Shout out: Using LunarVim with LSP and TreeSitter. The other thing I'm enjoying is that libraries can use them to make things happen more automatically. I believe it was Typer (the CLI argument parsing library) where if you declare an argument to a function as "files: List[Path]", it understands that the argument will take one or more files, or "-" to mean stdin. If you just say "file: Path", it understands it is a singular file. I was curious about type hints when they first came out, wasn't really expecting to use them but they seemed cool, but now I'm totally sold.
- totony 5y ago>My editor now has a fairly deep understanding of my code, and can tell me of all sorts of surprising errors I'm making before I run the code. I agree this is useful, but to me the most useful feature of types are the self-documentation. It's crazy the difference between a non-typed library with shitty documentation vs a typed library with shitty documentation.
- kadoban 5y agoThe types on stitty-documented code often do depend on the types actually being checked though. Otherwise you need to author to be diligent in their types, but if they're bad in their other docs, that seems unlikely.
- majormajor 5y ago> But as a general rule: You don’t know if there really is a tool in place to check them. You especially don’t know this when you join a new project, but it’s also a little hard to tell afterwards. Did the mypy task in your build pipeline silently break? Maybe mypy is misconfigured? Maybe it spits out errors but does not cause build jobs to actually fail? What if mypy has a bug? What if mypy is not even complete and doesn’t cover all cases? This seems like an extreme overstatement and a sign of a very weird team environment. Are you not running your linting and validation locally? Heck, when dealing with some poorly-typed external code, I run mypy manually to help me figure out what the stupid types I need to assign even are. This is far from ideal, but in lieu of a better solution, it works for me. I just find the idea that people would be adopting typed Python and then completely ignoring the type-related tooling a bit wild. And sure, libraries can have bugs, you can open yourself up to big holes with Any... and in cases where I'm super worried about things like that, I'm generally not using Python. But I'd rather use Python with type hints + use the tooling in a sane way then not use the type hints at all.
- linsomniac 5y agoHot take: If you think for a moment about the feature name, "type hints", many (all) of the objections the author has become clear. It is not called "static typing". It's called "type hinting". Based largely on the name, I wouldn't expect it to error at runtime if you tell me 'hello' is an int. That's just a type hint. I WOULD expect a static analysis to flag is, and mypy indeed does.
- reikonomusha 5y agoAren't they called "annotations" by PEP 484? Annotating certainly sounds stronger than hinting, but one must dive in and read the PEP to see they in fact do nothing except stash away metadata in a dunder attribute.
- valcron1000 5y agoIf you're willing to drop all dynamic stuff and deal with a smaller library ecosystem I would highly recommend trying Haskell. At some point I feel like it's Python 5
- dgan 5y agoI kinda wish OCaml had more traction
- moelf 5y agoMy personal "disappointment" is: it doesn't do anything for the runtime with all the extra work and headache. I.e. it feels like Julia but without the elegance of multi-dispatch and performance.
- dlivingston 5y agoTime-to-first-plot would like a word.
- reikonomusha 5y agoThat hardly has to do with type checking, and instead their compiler design.
- voz_ 5y agoUse pyre.
- travisgriggs 5y agoI have found optional typing to be a great example of an 80:20 trade off. I add type annotations to the easy stuff. I get a huge bang for that. I find that once I go past the “easy” annotations, I get less and less back from that. Between the IDE and my own annotations it catches 95% of trivial type errors.
- jsmeaton 5y agoAdding type hints to Python has increased my productivity by at least a factor of 10. They allow you to reason about code in a local function without having to track back up dozens of call sites to ensure you're getting what you think you're getting. That alone is worth the price of admission. Both when editing code or reviewing someone else's. It's fantastic, particularly in a very large code base. The editor experience only increases that factor as you can navigate a lot more freely. Even for small code bases type hints are a revelation. Knowing if something is nullable or not, alone, has caught 100's of bugs in waiting. Most of the complaints here feel like attacking a strawman, particularly the ones arguing what's the point if you're not running mypy. Run mypy! It's like saying what's the point of writing unit tests if you don't run the test suite. For any sufficiently large code base you absolutely should be running mypy with any plugins for your framework of choice added. For heterogeneous dictionaries use `dict[str, object]` and then you're forced to use the existing duck-typing mechanisms you're used to. Or, you refactor into better types and/or structures. Is there friction? Sometimes. You don't have to annotate everything. If the cost is too prohibitive for a particular structure or function, ignore it. Sometimes there are mypy bugs that make writing correct code impossible. # type: ignore[reason] that sucker. Don't throw the baby out with the bath water. We use a flake8 linter to enforce that all new or modified functions at least annotate their return type which makes interacting with functions quite a bit nicer, and encourages all devs to at least do the minimum. Usually you find that most args are appropriately typed at the same time.
- tootie 5y agoI'm baffled by people loving type hints in python when strongly typed languages have been widely available for so long. This is why people liked java and c#.
- minism 5y agoSame thing happened to the JS world with typescript (though typescript seems more powerful than python type annotations). Its fine though - I'm glad the culture is trending towards understanding that strong typing saves you time rather than causes you extra time. This is true even for very small and simple programs, and even if you're the only developer.
- ttymck 5y agoLook there's a lot of good, long winded comments here. If anyone is like me and scrolls for an easily digestible one: here's the TLDR. Eventually you'll get fed up with not knowing what type each argument to an API call needs to be. You'll either get on board with python type hints, or you'll graduate to a typed compiled language, or you'll languish in the trough of python productivity.
- goodoldneon 5y agoTypes help to encourage readable code. If it's hard to add type annotations to a function then the function is too complicated. I've seen this with wildly polymorphic functions that needed dozens of overloads to properly type... which means that engineers need to hold all that complexity in their heads
- avl999 5y agoI find it interesting how we have come full circle on static typing. When I was in University 2009-2013... and years leading up to it, dynamic typing was becoming the hot thing after years of Java/C/C++ dominance. Statically typed languages were looked down upon and talked about as being analogous to "Enterprise", "suit and tie" type soul crushing software development. We had people fulling in Ruby/Rails bandwagon, Java/C/C++ starting to become deprecated from university curriculum in favor of Python... JS starting to eat the front end and HN startups were talking about how they write their entire stack in a flavor of Lisp. And now, just a few years later- Rust, Go are two of the hottest languages around, TypeScript is eating JavaScript, Python/Ruby have added static typing constructs, C# continues to do well in its niche and even Java of all languages has become somewhat cool again even though being Oracle product. It's been an amazing transition to watch in action play out in front of my career, I can't even imagine those who have been in the industry for 30-40years who have probably been through a dozen of these cycles.
- reikonomusha 5y agoGive it a few more decades and maybe we'll come to accept a Hindley-Milner system of the 1970s, like that of Standard ML. And maybe a few more decades after that to go back to the dynamic typing of the 1950s, like that of Common Lisp. :)
- rahimiali 5y ago> "What you really want is a compiler, isn’t it?" The thing is, Python is just as compiled as, say Java. Python converts your code to byte code, then executes that bytecode in its VM. These are the same steps Java takes. So this "whoops" doesn't work for me: "Some language that’s as easy to use as Python and it should be compiled and with good static typing, but it should also not be compiled because then it wouldn’t be as easy to use as Python anymore. Whoops?". The reason the typing in Python is lax was entirely a choice. Maybe not a good choice, but it certainly has nothing to do with "compiled" vs "interpreted".
- maxloh 5y agoThere is mypyc and Cython, which compile Python to high performance machine code.
- kortex 5y agoThat's not really a good definition of compiled. Interpreted vs compiled is very much more a continuum than it was however many years ago when these terms originated - you had compiled ALGOL and interpreted BASIC, and little in between. Rather, you have to look at it like an attribute based categorization: Compiled: - types known at compile time - limited runtime features like stack traces, introspection - working closer to primitive data types Interpreted: - dynamic, with lots of indirection - wrapped data types (eg PyObject) vs primitives - rich runtime with stack traces, introspection, monkey patching
- bayesian_horse 5y agoA type checker doesn't make a statically typed language. Also, yes, the program will "run" with failed type assertions. Compare this with Typescript, where by default the compiler will refuse to compile the code when type errors are encountered. But there are other Typescript compilers that are faster and don't typecheck at all, they just strip the syntax. If you want the strict behavior, you need to prevent the program from running when typechecking fails. That is entirely possible with mypy.
- smohare 5y agoThis article was written by someone who doesn’t read or write much Python, obviously. Why is it on HN?
- revskill 5y agoBecause many people on HN don't read or write much Python.
- nurettin 5y agoMaybe the title should have been "mypy has a bug and I'm going to spin it into a language problem because I don't like Any"
- tbrownaw 5y agoThey're not perfect, but they do make the syntax highlighting and autocomplete work better.
- theptip 5y agoI didn’t really connect with any of these objections. Python type hints are very permissive and you need to turn them up in strictness to get enforcement. No big deal for me. But moving between a TS and Python codebase, I just find TS much easier to work with. Maybe it’s that type bindings are more widely defined in libraries (though typeshed has quite a few now). Or maybe it’s something about TS being easier to define type vars / infer types in my IDE? I can’t really put my finger on it.
- anamax 5y agoType systems are great for catching representation errors. However, the important errors that I make are "kind" errors. Type systems can verify that you're adding two ints, but won't tell you when you add the number of bananas to the number of oranges. Of course, both numbers contribute to the total number of snacks.
- jlrubin 5y agomy experience with python's optional type system was that the simple stuff works very well, but when you try to go down a type rabbit hole for more advanced stuff involving generics it becomes really unworkable, inconsistent, and hard to dig yourself out of. but for little things, like just function signatures, it's great!
- jlrubin 5y agofwiw i was able to successfully port this complex project into rust's type system.
- kortex 5y agoThis article is so hopelessly mis-informed, that it's practically hard to read without screaming "that's not how any of this works!" Most of their main arguments - type hints can be wrong, they can be ignored, and they don't inform you in a useful way about program state because of this - all evaporate as soon as you start using the correct tooling. My stack is pycharm, mypy, pydantic, sqlalchemy stub, several mypy plugins, black, isort, tabNine completion, and a bunch of custom scripts/Make to automate the common tasks. I'm not even sure I'm on the same planet as the author. I can practically spot incorrect type hints, mismatched types, weakly defined interfaces, from orbit, that's how well they are highlighted. Since every type is known, between pycharm and tabnine I can type 2-5 keys and spit out entire lines of code. And since it's all typed, automatic refactor is a breeze. I remember the dark ages, before type hints. It was rough. I lived in the REPL. Write 3 lines, run, Exception. Write 3 more lines, run, NoneType error. Ad nauseum. Now I write for hours on end and don't wince when I hit execute. And I don't have to go bug coworkers with questions like "hey what keys are in this dict when we redirect from the oauth endpoint". Sure, I have my gripes, but it's mostly with the lack of power of the type system, like lack of higher kinded types. But I'm confident it'll get there. Come to the typed side. We have less mental fatigue and screaming at neverending runtime oopsies.
- hummingn3rd 5y agoI was curious of seeing if pydantic was mentioned, thanks! We use most of the same tooling as you, I'm always interested in improving our tooling, would you be willing to share your mypy plug-ins names or maybe most useful tools for inspiration?
- qayxc 5y agoAs long as you don't have to rely on 3rd party libraries, sure, type hints are fine. Many popular libraries, however, don't have type hints or use them inconsistently (looking at you numpy, pytorch, tensorflow, scipy, ...). Always great fun to see function signatures that use type hints for the parameters and return Any. So it really depends what kind of code you write - web frameworks might be fine, data science and ML is definitely not.
- 5y ago
- aswerty 5y agoType hints are a god send in Python if you want to use the language for anything beyond scripting (or single developer code bases). Without type hints you don't realise how crazy your data structures get in Python. Trice nested dictionaries getting passed around, or pandas running wild across your code base, and on it goes. Instead with type hints we now have insight and can have meaningful discussions on the data structures flowing through our system. Our team is yet to adopt mypy into our build systems, but hopefully we will introduce it soon.
- nwatson 5y agoPyCharm with type-hinting and "inspections" (which include pseudo-static analysis for appropriate type use) have only added to the awesomeness of great code navigation, refactoring, auto-completion, code-formatting, etc. If you're going to have type-hints, you need pseudo-static analysis.
- nyuszika7h 5y ago> and in new versions of your type checker, you have to make sure that they didn’t change their meaning and that they didn’t introduce new flags that you really, really should use. That's what the --strict flag is for, which the author even quietly uses in a later example without explaining it. Though it may be too noisy to immediately turn it on in some projects. As for the example of getting something returned from the network that has a mismatching type, there's no way mypy could guess that. You'd have to add an explicit `isinstance(foo, int)` check or use a runtime type checker. The author does have a point that people might simply use wrong type hints if they don't have a proper type checker set up though. I've seen so much code with `any` instead of `Any`, `[foo]` instead of `list[foo]`, etc. as type hints. Using something like pre-commit and/or editor plugins to run mypy automatically while editing is probably the best. But it's true that even then, without --strict or equivalent, you can too easily satisfy the type checker by simply annotating something as a `dict` or `list`, without explicitly using `Any`. Still, I don't think this means we shouldn't use type hints at all. It could definitely be more beginner-friendly, but most of the mentioned issues can be addressed with proper configuration.
- physicsguy 5y agoI like type hints, but trying to retrofit it into an existing project I’ve found difficult, because you end up with Union[type1, type2, type3] in some places.
- t43562 5y agoCorrectness in Python is all about unit tests - if you don't bother with them then you're playing with fire (and of course I often "play with fire"). Type hints .... well they help the IDE to autocomplete which is great. They also help you to get the order of parameters in a function/method call correct which is useful if the parameters aren't all the same type! I converted a medium sized project to type hinting once. The original author wrote no tests and obviously didn't design it to be testable so I was looking for some small way to make it less horrendously unmaintainable. Every test run of the source took hours and there would be some trivial syntax error or whatever right at the end. Type hints weren't so difficult and I hoped that they would "staunch the bleeding" while I tried to get it into testable shape. In this case they did almost nothing - didn't help me stop a single bug - probably because most types were "str" but that's not the fault of the hinting system as an idea, right? It's just an unprofitable load of work in particular situations. Static typing fans are always going to be disappointed by Python and it's great because there are other languages for them. For the rest of us we can use them where it turns out to be profitable to us. Unit tests are, however, by 1000x, more important.
- arinlen 5y ago> Correctness in Python is all about unit tests - if you don't bother with them then you're playing with fire (and of course I often "play with fire"). But Python does support type hints, and tools like MyPy do use those type hints to evaluate correctness. It seems to me that Python's type hints are indeed Python's way to check for correctness. Also, unit tests don't verify correctness. They only serve to check whatever small set of ad-hoc invariant developers put up.
- t43562 5y agoYou can have a program with correct type handling that doesn't work but with unit tests you have a program that works and documentation (in the form of the test) about the ways in which the programmer expected it to work. That's why I find type hinting to be relatively high effort for relatively low benefit and choose to use it only where I feel it makes life better. The optionality suits me. It's a nice to have but that's all.
- runeks 5y ago> Python is a dynamically typed language. By definition, you don’t know the real types of variables at runtime. I think you mean compile-time and not runtime. There’s not much use in knowing the type at runtime, since it only enables you to print a better error before crashing (“Expected type: x, actual type: y” instead of “AttributeError: 'str' object has no attribute 'append'”). Types are only truly valuable at compile-time, where they can prevent compilation of invalid code. This is the reason many statically typed languages use type erasure, which removes type information from the compilation output. In fact, the type-checking phase can happen even earlier than the compilation phase. This is useful e.g. in an IDE, where you care about type errors but not necessarily about running your program.
- davidatbu 5y agoI disagree diametrically with both the general sentiment of the article, and every major point that was made in it. Every point in this blog post strikes me as either (1) unaware of the tooling around python typing other than mypy, or (2) a criticism of static-typing-bolted-on-to-a-dynamically-typed-language, rather than Python's hints. Regarding (1), my advise to OP is to try out Pyright, Pydantic, and Typeguard. Pyright, especailly, is amazing and makes the process of working with type hints 2 or 3 times smoother IMO. And, I don't think points that fall under (2) are fair criticisms of type *hints*. They are called hints for a reason. Otherwise, here's a point-by-point response, either recommending OP checks out tooling, or showing that the point being made is not specific to Python. > type hints are not binding. There are projects [0][1] that allow you to enforce type hints at runtime if you so choose. It's worth mentioning that this is very analogous to how Typescript does it, in that type info is erased completely at runtime. > Type checking is your job after all, ...[and that] requires maintenance. There are LSPs like Pyright[2] (pyright specifically is the absolute best, IMO) that report type errors as you code. Again, this is very very similar to typescript. > There is an Any type and it renders everything useless I have never seen a static-typing tool that was bolted on to a dynamically typed language, without an `Any` type, including typescript. > Duck type compatibility of int and float The author admits that they cannot state why this behavior is problematic, except for saying that it's "ambiguous". > Most projects need third-party type hints Again, this is a criticism of all cases where static types are bolted on dynamically typed languages, not Python's implementation specifically. > Sadly, dataclasses ignore type hints as well Pydantic[3] is an amazing data parsing library that takes advantage of type hints, and it's interface is a superset of that of dataclasses. What's more, it underpins FastAPI[4], an amazing API-backend framework (with 44K Github stars). > Type inference and lazy programmers The argument of this section boils down to using `Any` as a generic argument not being an error by default. This is configurable to be an error both in Pyright[5], and mypy[6]. > Exceptions are not covered [like Java] I can't find the interview/presentation, but Guido Van Rossum specifically calls out Java's implementation of "exception annotations" as a demonstration of why that is a bad idea, and that it would never happen in Python. I'm not saying Guido's opinion is the absolute truth, but just letting you know that this is an explicit decision, not an unwanted shortcoming. [0] https://github.com/RussBaz/enforce https://github.com/RussBaz/enforce [1] https://github.com/agronholm/typeguard https://github.com/agronholm/typeguard [2] https://github.com/microsoft/pyright https://github.com/microsoft/pyright [3] https://pydantic-docs.helpmanual.io https://pydantic-docs.helpmanual.io [4] https://github.com/tiangolo/fastapi https://github.com/tiangolo/fastapi [5] https://github.com/microsoft/pyright/blob/main/docs/configuration.md#type-check-diagnostics-settings https://github.com/microsoft/pyright/blob/main/docs/configur... [6] https://mypy.readthedocs.io/en/stable/config_file.html#confval-disallow_any_generics https://mypy.readthedocs.io/en/stable/config_file.html#confv...
- wodenokoto 5y agoA lot of people saying author isn't smart/educated enough about the topic, but I kinda agree with him, that they are disappointing. From a "normal" programmers point of view, they are weak and don't really safeguard you well enough out of the box. Apparently you can install and setup a billion 3rd party libraries in your code editor and a CI pipeline to get a really good workflow, but that just shows that you need to be an expert in order to use these.
- lars512 5y agoI love the gradual typing approach, and have found it makes codebases better to maintain, even if some libraries like pandas are a total pain. My biggest gripe is the conflicting warnings between mypy and pyright. Language servers use pyright by default in the editor, but I strongly believe a Python project shouldn't require nodejs as part of its required CI toolchain. So all my projects use mypy in strict mode in CI. Basically this means that mypy is the standard to meet, and that there are persistent warnings in the editor which I have to ignore.
- pkrumins 5y agoPython is becoming a Turing tarpit language that’s black-holing on its own syntactic complexity. Soon every single ASCII character will have a special syntactic meaning and the syntax itself will become Turing complete in more than one way, similar to C++ that has already collapsed in syntax hell. JavaScript is following the same path by adding every feature from every other programming language. Soon all programming languages will have exactly the same features where everything is possible but nothing is doable or practical.
- dgan 5y agoLanding in a large-ish python project without type annotations is a pain. Author says that he won't use type annotations because they "can be wrong", well, you only rely on variables names and documentation for that, you have even less chance to get that right. Is that "line" variable a "LineInvoice" or "InvoiceLine" (yes, two different classes) ? Oh, right, both can be used in this place exclusively because one is subset of the other... sigh
- CrLf 5y agoPython's base philosophy is duck typing. Whenever I read complaints like this the root cause is almost always trying to turn Python into something that it isn't instead of embracing what it is (if this isn't feasible, then Python is the wrong choice). Programming in Python worrying about types instead of behavior reminds me of the quote "you can write FORTRAN in any language".
- dgan 5y agoWell, the problem is more often than not, I am an employee. I won't come to a company and tell them "you have been using that wrong". So while correct, your statement is void of any actionable advise
- lysecret 5y agoLove typing, if you are writing code with a lot of Data Frame Inputs and Outputs I encourage you to check out Pandera.
- lysecret 5y agoAbout this section: Sadly, dataclasses ignore type hints as well this is excatly what pydantic was made for. As well as its integration with FastApi. FastApi, is really the most beautiful way, I have seen. To use the python type system to its fullest.
- da39a3ee 5y agoI agree with everything in this article. The fact that nothing is necessarily checking them makes a codebase full of them too misleading. They become cargo culting; and as the article says their special syntactic status makes them look “official”. Typescript is much better since you can’t avoid them being checked. And that’s said as someone who spent the last decade writing Python, in later years with type hints. There’s also a mypy option that is not on by default but that is absolutely required to avoid misleading false negatives: —-check-untyped-defs
- whiplash451 5y agoI would argue that doing this kind of stuff is bad design. ```foo = { 'hello': 'world', 'bar': ['baz'], } ``` Don't put it on the language not to be able to deal with this kind of stuff.
- Jiejeing 5y agoThe author seems to have unreasonable expectations of the python typing implementation, most of which can be fixed with mypyc and stricter flags. They also did not check the concept of gradual typing which is key to why everything is not strict by default. I too am disappointed a bit by the type hints because they are not expressive enough for me, and some natural python constructs are hard to express. And because mypy has bugs I encounter from time to time.
- igortg 5y ago> www.uninformativ.de Domain name checks out :)
- wheelerof4te 5y agoThe main problem with type hints for Python code is that it changes the way you think about writing Python. Before, it went something like this: 1) Install Python (if you don't have it already) 2) Install your favorite text editor 3) Write some Python! Now, it goes something like this: 1) Install Python 2) Install your favorite IDE 3) Install plugins for your IDE 4) Install black, mypy, flake8 plus some other nonsensical "helper" library 5) Don't forget your poetry, gotta have that 6) Be careful to pick only 3rd party libraries that have good type hints.. 7) God help you if you try writing something yourself, let your IDE do that. Type hints make not only your code more complicated and unreadable. They complicate your entire workflow.
- tomerv 5y agoHow did you get from type hints to black, not to mention poetry? Seems like you're just complaining about there being a mature ecosystem around Python, and the implicit expectation to use it.
- wheelerof4te 5y agoAnd here I thought my explanation at the bottom covered this. Let's try again: Python has become a mess. It is no longer a simple productive language to get into like it used to be. Now, you are expected to buy into it's ecosystem, like it is C# or Java. Well, it is not. It's Python and I am truly sad they are killing it with thousand cuts.
- tomerv 5y agoYes, it's getting more complicated. Yes, there's a whole ecosystem being built around it, and the line between language and ecosystem is blurry. And indeed, there's a hidden expectation for any Python developer to buy into the whole ecosystem. But that's just a symptom of a mature programming language that's used in a variety of complicated scenarios. You don't have to do it all, and no-one is forcing you. You can always write your one-off script without black, flake8, type hinting, or anything of the sort. If it's just your script then no-one will even know. On the other hand, if you want your code to be part of the larger ecosystem, then you're expected to write it in a conformant way (e.g. pep8 formatting). And that's a good thing!
- tpoacher 5y agoAll the problems the author seems to have seem to be problems of "false expectations" rather than type hints lacking value per se. In which case, I fully declare, publicly, that I am very disappointed with numpy, because it doesnt have good coffee making facilities out of the box.
- shreyshnaccount 5y agoI write data science code, it's a mess. Type hints have saved me a lot of time and headache.
- twelve40 5y agoI wonder who, ever, thought that weak typing python- or raw js- style, was a good idea? Come to think of it, is there a single redeeming quality of weak typing in those languages other than "easier to wreak havoc and quicker to write crazy buggy shit"? There is probably that stoic school of thought that if you are forced to walk around a construction site without a helmet, it will make you a more thoughtful and better worker, but... come on
- mmcnl 5y agoI actually enjoy the typing in Python. The only problem is lack of support from third-party libraries. I find myself fighting the typing errors so often by adding: # type: ignore. Especially pandas gives so many errors. Type hints are included but they are often just plain wrong.