8 ms·
The different uses of Python type hints
- BeefySwain 4y agoA few other examples for the sections given: Runtime behaviour determination: the stdlib [dataclasses](https://docs.python.org/3/library/dataclasses.html#module-dataclasses https://docs.python.org/3/library/dataclasses.html#module-da...) Dataclasses is notable because it's the only example (I'm aware of) of type hints effecting runtime behavior as part of the stdlib. Compiler instructions: mypyc was (one of?) the first to do this, but Cython actually supports this natively now, and is much more active than mypyc is last I checked.
- FreakLegion 4y agoThe Annotated type is worth mentioning as well. Today in something like SQLModel you do (from the readme): class Hero(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) And that's fine. I wouldn't necessarily change anything here. Annotated gives you the option of approaching things in a different way, though. class Hero(SQLModel, table=True): id: PrimaryKey[Optional[int]] = None I have some use cases where the alternative approach is useful, like quantification of class fields or function arguments.
- eirki 4y agoFastApi very recently added support for Annotated, and now recommends using that over default arguments. https://fastapi.tiangolo.com/release-notes/#0950 https://fastapi.tiangolo.com/release-notes/#0950
- amethyst 4y ago> Dataclasses is notable because it's the only example (I'm aware of) of type hints effecting runtime behavior as part of the stdlib. FWIW, `typing.NamedTuple` did this in Python 3.5, three years before dataclasses was introduced in 3.7. class Foo(typing.NamedTuple): a: int b: str f = Foo(a=1, b="hello") print(f.b) # "hello"
- BeefySwain 4y agoGreat catch, how could I forget!
- auscompgeek 4y agoVariable annotations were only added in Python 3.6. Defining a typed namedtuple in Python 3.5 looked like this: Foo = typing.NamedTuple('Foo', [('a', int), ('b', str)])
- SethMLarson 4y agoProtocols with @runtime_checkable fit your description!
- throw_a_grenade 4y agoDataclasses, like typing.NamedTuple, do not care about type hints: >>> @dataclasses.dataclass ... class D: ... x: int ... >>> D('a') D(x='a')
- jselysianeagle 4y agoThe idea with type hints in Python though is that they’re meant to be checked using some static analysis tool like mypy/pyright/etc. The runtime behavior for the most part remains unchanged in the sense that the Python interpreter won’t enforce the types in cases such as the one you’ve provided.
- FreakLegion 4y agoDataclasses do care about type hints in some cases, for example when determining what counts as a field. @dataclass class A: a: int = 0 b = 1 >>> A(a=1, b=2) TypeError: __init__() got an unexpected keyword argument 'b'
- eirki 4y agoThe only exceptions I can think of is https://docs.python.org/3/library/typing.html#typing.ClassVar https://docs.python.org/3/library/typing.html#typing.ClassVa...
- eesmith 4y agoI managed to find type hints affecting runtime behavior in functools.register. https://docs.python.org/3/library/functools.html?highlight=functools#functools.singledispatch https://docs.python.org/3/library/functools.html?highlight=f... > To add overloaded implementations to the function, use the register() attribute of the generic function, which can be used as a decorator. For functions annotated with types, the decorator will infer the type of the first argument automatically: That appears to be the only other case.
- Animats 4y agoThis sort of thing is why I gave up Python. I could see having strong typing. Or optional strong typing. But unchecked type hints are just silly. The way everybody else seems to be going is strong typing at function interfaces, with automatic inference of as much else as can be done easily. C++ (since "auto"), Go, Rust, etc.
- maleldil 4y ago> The way everybody else seems to be going is strong typing at function interfaces, with automatic inference of as much else as can be done easily Both mypy and pyright will do that. If your function return type is annotated, they will infer the type of the receiving variable. If you have two branches where a variable can receive two types, pyright will infer the union type. Similar for None. Example: a = input() if a.isdigit(): x = int(a) else: x = a reveal_type(a) reveal_type(x) Pyright output, stripped of configuration noise: typetest.py:6:13 - information: Type of "a" is "str" typetest.py:6:13 - information: Type of "x" is "int | str" Mypy doesn't allow this. It infers `a` as `int` and rejects the second assignment. The only times I need to annotate local variables are (1) the function isn't typed, so it gets inferred as Any (2) I'm initialising an empty collection, so its type might get inferred as e.g. `list[Unknown]` (pyright; mypy can infer the element type). Is there something inference-wise that you miss in Python compared to C++ or Go? PS: The larger problem to me is the inconsistence between pyright and mypy, the leading type-checkers. Sometimes issues are raised between them and they work to achieve agreement, but I believe the two issues highlighted above (unions and collections) are design choices, unlikely to change.
- klyrs 4y ago> Both mypy and pyright will do that. This still makes me seethe. We have pip, poetry, conda, and more. The Python folks knew that multiple incompatible systems would arise from a grammar spec without a behavior spec. And here we are. Python doesn't do anything useful with the types, but third-parties are left to their own devices.
- 4y ago
- Heston 4y agoThe only reason to consider type hints is for a performance increase and there wasn't any mention of that. What can you really expect from using type hints accurately?
- gaganyaan 4y agoType hints are great when using FastAPI. Your inputs are automatically validated, and you get a /docs endpoint that tells people what to expect from your API. I'd say performance is far from the only reason to consider type hints.
- maleldil 4y agoSimilarly for Typer, which is literally "the FastAPI of CLIs"[1]. Handy to type your `main` parameters and have CLI argument parsing. For more complicated cases, it's a wrapper around Click. [1] https://typer.tiangolo.com/ https://typer.tiangolo.com/
- abdullahkhalids 4y ago> Compiler instructions > I don’t know how many people are doing this, but tools like mypyc will use type hints to compile Python code to something faster, like C extensions.
- dragonwriter 4y ago> The only reason to consider type hints is for a performance increase No, the reason to consider type hints is because it makes it easier to understand existing code and write new code that interacts with it correctly. Comprehensibility and correctness are more important than performace.
- Heston 4y agoIn a dynamically typed language, that's what comments are for. Since you didn't need types specified in the first place, why would you have trouble interacting with it? Comprehensibility and correctness are just as important as performance.
- abraxas 4y agoThe issue that I have with Python type hints is they they don't go nearly far enough in describing the data being manipulated. Specifically, I'm thinking of stuff like the dimensionality and cardinality of Numpy arrays or Pandas frames. Usually that's the stuff where I have most questions when I look at Python code and the type system as it's being used now offers no help there.
- Jeff_Brown 4y agoYou want dependent types!
- Spivak 4y agoPython can actually do (some) dependent types with generics but it's not pretty. The only real use-case that is both possible and worthwhile I've found is being able to say a value is a T if there's a default and an Optional[T] otherwise.
- still_grokking 4y ago> Python can actually do (some) dependent types with generics Could you show some examples?
- OJFord 4y agoI'm not sure how a python annotation/type system could possibly do that? If numpy/pandas had different types for different cardinalities it would work today. You just need those libraries to embrace it really, then you could theoretically have type constructors that provide well-typed NxM matrix types or whatever, allowing you to enforce that [[1,2],[3,4]] is an instance of matrix_t(2, 2). I don't see how python could possibly make such inferences for arbitrary libraries.
- Mehdi2277 4y agoPEP 646 Variadic generics, https://peps.python.org/pep-0646/ https://peps.python.org/pep-0646/, was made for this specific use case but mypy is still working on implementing it. And even with it, it's expected several more peps are needed to make operations on variadic types powerful enough to handle common array operations. numpy/tensorflow/etc do broadcasting a lot and that probably would need a type level operator Broadcast just to encode that. I also expect the type definitions for numpy will go fairly complex similar to template heavy C++ code after they add shape types.
- maleldil 4y agoI'm a heavy user of type hints and enable pyright and mypy's strict modes whenever possible. However, you can't always be strict: if you use almost any package in the data science/ML ecosystem, you're unlikely to get good type inference and checking[1]. In those cases, it can still be useful to type some parameters and return values to benefit from _some_ checking, even if you don't have 100% coverage. Type hints also bring improved completion, which is nice too. [1] For example, huggingface's transformers library decided to drop support for full type checking because it was unsustainable but decided to keep the types for documentation[2]. There are stubs for pandas, but they're not enough because pandas has a tendency to change return types based on the input, and that breaks quickly. [2] https://github.com/huggingface/transformers/pull/18485 https://github.com/huggingface/transformers/pull/18485
- Jeff_Brown 4y ago> There are stubs for pandas, but they're not enough because pandas has a tendency to change return types based on the input, and that breaks quickly. A mechanism like Haskell's type application seems like it could solve at least most, maybe all of those problems.
- ParetoOptimal 4y agoI can confirm from experience using Frames[0] and type applications together this is very much the case. 0: https://hackage.haskell.org/package/Frames https://hackage.haskell.org/package/Frames
- Jeff_Brown 4y agoI greatly hope and somewhat expect AI code generation will lead people to focus more on correctness: tests, type signatures, and (ideally, eventually) dependent types.
- 1letterunixname 4y agoNot to start a religious war, but I think Ruby screwed-up on gradual typing making it too complex and too many steps. Attempting to maintain perfect Microsoft-legacy-style compatibility rather than have a hard change is the greater failure than having a truly new major version rather than arbitrary marketing increments. Crystal is compiled with static typing but looks like Ruby. The type specification it uses emulates gradual typing of dynamic languages.
- Kwpolska 4y agoHow does Ruby’s system look? Python’s type hints are fully optional and opt-in, typed and non-typed code works the same (even though type checkers may complain about the latter).
- pansa2 4y agoI believe the Ruby designers have refused to add syntax for type hints, so they need to either be in comments on separate lines from the code itself or even in a separate file. They are therefore less ergonomic to use - but the increased separation from the code means that they are mostly used purely as (machine-verifiable) comments. On the other hand Python's type hints tend to be deeply intertwined with the code, and are even required to access new language features such as dataclasses. The two languages take such different approaches because their designers have different feelings about static typing. Guido and the Steering Council seem to want Python to be as statically-typed as possible, whereas Matz thinks "static type declaration is redundant" [0]. [0] https://evrone.com/yukihiro-matsumoto-interview https://evrone.com/yukihiro-matsumoto-interview
- firatsarlar 4y agoIf you accept my -in advance- apology, why this type thing seem ugly -distraction,complex, hard to act, ...- to me ? I'm not against it , as in TS (non enforced type checking ), it is a lovely addition to python, but I'm really struggling to read, write and .. this syntax . Not sure if it is python's nature, but as most of us, C, C++, ...., TS this is a journey, evolution , but the root C is some kind of cult we attached to. Is it preventing me to love this thing ( thanks for effort ) Do not know?
- ggm 4y agoAdditions to language always confront syntax expectations. Some people can see through syntax to semantic intent, alas I am not one and the utility of a syntactic form goes (to me at least) beyond expressiveness to comprehension: if your syntax confuses then how can anyone comprehend? Haskell dies in syntax.
- galbar 4y agoSome time ago I made a dependency injector[0] in Python using type hints. I have always enjoyed playing with type systems and I wanted to explore Python's. I remember that it felt rough. I had issues specially with funcions using veriadic types in generics. I also remember having issues with overloading a function: sometimes it would go for the more generic one, instead of going for the more specific one when inferring types. I managed to solve all of that. Unfortunately, that happened some time ago and I don't remember the specifics, only that it was a fun project to develop. I use it frequently in other projects. [0]: https://gitlab.com/applipy/applipy_inject https://gitlab.com/applipy/applipy_inject
- t43562 4y agoI inherited a python based build system which had been written without any unit tests because....it's a build system right? right?? Anyhow it was the kind of thing where you'd build for 20 minutes (Android) and then have some kind of trivial error in the python code at the end of the build. You fix that and run again and waste another 20 minutes on the next thing. I couldn't do unit tests all at once because of the design not having any way of accommodating them. I needed something to stop the enormous waste of time. So I added type hints. The IDE should show me when illogical things were being done with parameters to methods/functions. It was fairly quick compared to a total refactoring but not effort free. I barely noticed any effect. Didn't catch a single error. Eventually I created a kind of dummy version of Android that "built" in a few seconds and I tested against that first. That allowed me to speed up changes and get some refactoring done to make a few critical unit tests and the whole thing started to get under control. This anecdote has almost no meaning - you cannot conclude that type hints have no benefit because of one case - I just think that tests are almost always more important and hinting and the whole rigmarole of strong typing are much less of a panacea than tests are.
- atorodius 4y agoIMO type hints are mostyl about (significantly!) improving readability.
- aldanor 4y agoAlso about improving editor experience and having better auto-completion that's based on type hints.
- ElectricalUnion 4y agoPyCharm and VSCode can do a lot of reasonably smart refactorings when the code isn't just a pile of `typing.Any` and that's a huge quality of life for any non trivial code base.
- MrJohz 4y agoAgain, purely anecdotally, I've done similar things in both Typescript and Python, and I usually catch at least one silly type error in Typescript, but I rarely do in Python. That could be because the Python developers I was following were just so good, but I suspect it's more about the quality of the typecheckers. Typescript feels much better at finding errors in normal, idiomatic Javascript, whereas I feel that with Mypy, if I want the best results, I need to write code in a way that plays to its strengths. I've been told that Pyright is better but I've not tried it out properly. But yeah, your experience largely matches with mine, for Python at least.
- lmeyerov 4y agoFor a bit of a quantitative analysis on this, we had fun doing surveying programmers here, see Table 7 @ https://lmeyerov.github.io/projects/socioplt/papers/oopsla2013.pdf https://lmeyerov.github.io/projects/socioplt/papers/oopsla20... Ex: Programmers value types much more for documentation vs preventing bugs. I had not expected that answer!
- pansa2 4y ago> I enjoy using static types: 18% (+/- 8) That number seems to be from 2013. I imagine it would be much higher today - 10 years ago dynamic typing was at the peak of its hype cycle, and right now it seems to be in the Trough of Disillusionment.
- lmeyerov 4y agoThat's a legit hypothesis! Speaking as a scientist, I'd love to see a round 2 of this work to see how much things are the same vs different. The premise for the work was doing more serious sociological methods could help understand tough phenomena here & suggest new solutions, so bringing in longitudinal analyses would be fascinating. FWIW, if I remember right: - Languages like Java, C++, .NET were the most popular. Maybe iOS/Android apps too? - Buzz around then were Scala + Java (big data), Haskell, Elm, D, and the beginnings of Rust. - TypeScript was already a year or two in as well. But population-wise, probably still niche. - That was probably also some of the heaviest Node Nowadays, we also see heavy rises in dynamic languages: - Professional data scientists using Python & R. I think Python has become the #1 language for new folks? - Go looks like a statically typed language... until you compare it to modern C++, D, Rust, etc So I wouldn't be surprised to see a shift.. but then again, not at all obvious how much, and especially controlling for selection bias..
- IshKebab 4y agoYeah I've found when trying (and failing mostly) to convince Python developers to use type hints that they often think it's only to fix bugs and then resist because a) of course their code doesn't have bugs, and b) they've already written their code and discovered lots of bugs painfully at runtime, so they wouldn't get most of the bug-finding benefits anyway. They never appreciate that type hints make code easier to read and write and navigate and understand and maintain. Often it's Vim users that have never used a good IDE.