Static Typing in Python
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 130 | |
Author | ||
License | CC Attribution - NonCommercial - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/49980 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
EuroPython 202023 / 130
2
4
7
8
13
16
21
23
25
26
27
30
33
36
39
46
50
53
54
56
60
61
62
65
68
73
82
85
86
95
100
101
102
106
108
109
113
118
119
120
125
00:00
TouchscreenSelf-organizationSoftware maintenanceSoftware developerGoogolPoint cloudSoftwareMeeting/Interview
00:59
Software developerGoogolSoftwareSoftware maintenancePrice indexDynamical systemSystem programmingAerodynamicsSocial classFunction (mathematics)Attribute grammarCodeFrame problemLambda calculusModule (mathematics)Variable (mathematics)Axiom of choiceParameter (computer programming)Functional programmingInterior (topology)Programming languageQuicksortLine (geometry)BitIntegerSource codeOnline helpMultiplication signElectronic mailing listString (computer science)Axiom of choiceParameter (computer programming)Software developerVariable (mathematics)Combinational logicTypsichere SpracheBoolean algebraCodeLogic gateSummierbarkeitSocial classDifferent (Kate Ryan album)Computer configurationDampingLogische ProgrammierspracheMixed realityAdditionOperator (mathematics)AliasingKeyboard shortcutInstance (computer science)Correspondence (mathematics)Software bugNumberStatic random-access memoryDynamical systemPhysical systemObject-oriented programmingPoint (geometry)Right angleOverhead (computing)System callCasting (performing arts)Regular graphDisk read-and-write headReal numberSoftwareGoogolComputer animation
09:18
Function (mathematics)Static random-access memoryJava appletAerodynamicsAlgebraic closureLine (geometry)Maxima and minimaInformationProgramming languageLogicPredicate (grammar)Texture mappingQuery languageDatabaseParameter (computer programming)Product (business)Scripting languageMultiplicationPrototypeVirtual realityPhysical systemRun time (program lifecycle phase)Computer programSemantics (computer science)CodeSystem programmingFibonacci numberTheoryPauli exclusion principleConstructor (object-oriented programming)Fundamental theorem of algebraBuildingBlock (periodic table)Social classParameter (computer programming)Pauli exclusion principleStatic random-access memoryAttribute grammarProgramming languageCodeFunctional programmingComputer configurationRun time (program lifecycle phase)Line codeComputer programmingVirtual machineSoftware developerNumberMetadataArithmetic progressionSource codeLine (geometry)Product (business)IntegerMultiplication signOptical disc driveQuicksortPhysical systemCategory of beingPrototypeVariable (mathematics)Java appletSlide ruleRight angleGame controllerModule (mathematics)BuildingConstructor (object-oriented programming)Block (periodic table)TheoryTouch typingPiType theoryFibonacci numberDynamical systemMathematicsHypothesisSemantics (computer science)Universe (mathematics)Scripting languageSound effectInterior (topology)DampingSystem callGraphics tabletMereologyHuman migrationVirtualizationMessage passingComputer animation
17:37
ConsistencyAliasingTupleSocial classElectronic mailing listFunction (mathematics)Complex (psychology)DecimalNumberPrimality testIntegerString (computer science)StatisticsAerodynamicsError messageParameter (computer programming)Static random-access memoryGoogolFacebookInferenceRun time (program lifecycle phase)Module (mathematics)Computer fileSource codeLocal ringLetterpress printingDirectory serviceSoftware testingExecution unitScale (map)Line (geometry)CodeACIDUsabilityHuman migrationCode refactoringIntegerComputer fileRun time (program lifecycle phase)Variable (mathematics)Functional programmingSocial classElectronic mailing listLibrary (computing)Complete metric spaceCodeText editorMathematical analysisPoint (geometry)Function (mathematics)Integrated development environmentStatic random-access memorySoftware developerDifferent (Kate Ryan album)Single-precision floating-point formatoutputQuicksortAliasingGeneric programmingVirtual machineNumberMultiplication signError messageProduct (business)Graph (mathematics)Key (cryptography)Data dictionarySimilarity (geometry)Message passingDataflowDampingPlastikkarteTupleGoogolScaling (geometry)Online helpSelf-organizationLine (geometry)Execution unitUnit testingDynamical systemProcess (computing)Typsichere SpracheFacebookComplex analysisAreaInferenceMereologySoftware bugInstallation artRevision controlControl flowConstructor (object-oriented programming)String (computer science)Module (mathematics)Physical systemBitMultiplicationRight angleSystem callTypinferenzLinear codeStandard deviationParameter (computer programming)Limit (category theory)Computer configurationInterior (topology)Computer animation
25:56
Static random-access memoryString (computer science)Software developerFunctional programmingLine (geometry)Multiplication signQuicksortBuildingOrder (biology)Code2 (number)Online chatModule (mathematics)Computer animationMeeting/Interview
Transcript: English(auto-generated)
00:06
for making this possible. So next up, we have Dustin Ingram. He's a developer advocate at Google focused on supporting the Python community on Google Cloud. He's also a director of the Python Software Foundation, a maintainer of PyPy and an organizer for the PyTexas
00:22
conference. So welcome, Dustin Ingram. Very glad to have you here. Thanks, Jason. So I could probably guess for that intro, but where are you streaming from? I'm based in Austin, Texas. Austin. Is it hot and sunny there? It is right now, yeah.
00:43
Awesome. Well, I will turn it over to you, and awesome. All right, let me share my screen. Does that look good? OK. So hey, like he said, I'm Dustin.
01:02
I'm a developer advocate at Google. I am a director for the Python Software Foundation, and I work on PyPy. I'm not here to talk about any of that today. I'm here talking about static typing in Python. So quick pop quiz. Is Python dynamically or statically typed? And so it's sort of, think in your head, maybe what is the answer to this question?
01:23
So the answer is that Python is dynamically typed, but it can optionally be as statically typed as you want it to be. And so that answer might not make sense to you even if you've used Python for a while or if you are familiar with other static languages. And that's OK.
01:40
That's kind of the point of this talk. We're going to talk about what that means. And so the steps to understand the answer to that question are sort of this. We need to talk about types in Python, just regular types, type systems in general across other languages. We'll talk about dynamic typing in Python. And then finally, we'll be able to talk about static typing in Python. And once we understand those things,
02:00
we'll talk about how to use static typing when you should use it and maybe sometimes when you shouldn't use static typing. So let's talk about types. And specifically, let's talk about type, the built-in keyword in Python. And you might be familiar with this. So type tells you what something is, what an object is or what a variable is. So if I call type 42, Python will tell me
02:21
that it is class int. So I know that that's an integer. And I can do the same thing with floats and strings and lists. So you might say, OK, I recognize these as built-ins. They tell me what types things are. But I can also use them to change types or do sometimes what we call typecasting. And you'd be right, right? I could take a variable a.
02:41
And when I assign it to the value, we say that a is the type of an integer. And I could cast it. I could use that float built-in to turn it into a float. And I could use a string built-in to turn that into a string. And I could use lists built-in to turn that into a really ugly list. So I imagine some folks watching might have had a weird bug where they accidentally
03:02
got a string turned into a list. And guess what? That is a type error. You, if you've experienced that before, you're definitely in the right place. So why does Python let that happen? So it would seem like these are the only types that are available to us, right? The things that we can cast from one type to another. But these are actually just classes
03:21
that happen to have corresponding built-ins in Python. So basically it's kind of just doing class matching here, right? We can say whether the number 42 is an instance of the class int. And when we call type, it gives us that same class back. So it's sort of just a class and it's sort of a shortcut or an alias
03:40
for that class name. But there are other class types as well that don't correspond to built-ins. So for example, none, we've all sort of used the none built-in and we've seen none type before, but they're not the same. Similarly for a function, we don't say, when we initialize a function, we don't instantiate a class,
04:00
we say def func, but that has a class underneath it too. There's a function class and same for ellipsis and actually lots of other things as well. And the place where you can sort of find the classes that represent all of these things in Python that we might want to interact with is from the types module. So you can import types, this comes with Python and you get a whole list of different types of types. And the kind of fun thing about these is
04:21
if you wanted to, you could instantiate a class with a function type and put things inside it. But actually that gets pretty long and verbose and it's a lot nicer to just write normal Python. So when we say the Python is a dynamically typed language, what we mean is that a variable, once it's defined, can be any type.
04:40
We can initialize the variable, we can set it to be one type and we can change it. So for example, what type is A here, right? I'm importing random and I'm taking a random choice from this list. And that list includes an integer, a float and a string. So when I call type of A, this could be anything. It could be any of those three types that I put in the random options.
05:02
And so it could be a string, it could be an int or it could be a float. And Python doesn't care. Python lets us set A to be any of these value types and that is what we mean by dynamic typing. This means that arguments and return types of a function can also be any type. So the same is true for a function as it is for variables. The things that we return from functions
05:21
or that we pass to functions, they can also be any type. So in Python, when we write a function like this, how do we know what types this function is expecting, right? So if you saw this function somewhere and you didn't know what it does, what would you expect the argument types and the return type to be? So you might say, okay, well, I'm seeing that it's adding things together.
05:42
So maybe these are integers, right? And you'd be right. You could call this from the k function with integers and it would give you the sum of all those integers. But you could also call from the gate with strings and it would concatenate the strings into a single string. And actually this works for lists and really anything else that would support
06:01
this addition operator in Python. So we can say that the arguments to Frobenikke and the return type of Frobenikke are dynamic. And then this can cause problems though, right? Because if we don't have any way to sort of guarantee what the arguments are, we can have type errors. So for example, if I call it with two integers and a string, we can't do this because the addition operator
06:22
doesn't let us mix types like this. And so we get a type error because we're trying to combine integers and strings together in the body of the function. All right, so that's pretty confusing. How could we fix it? So one thing we could do is write really long and detailed docstrings about what the function expects
06:40
and what the function should return. And this is great for developers. And sometimes we do this. I don't do this. This is a lot of work and it's a lot of work to maintain this documentation. And on top of that, writing these comments while they're helpful for developers, doesn't actually guarantee that someone using your function is calling it correctly, right? These are just sort of like
07:00
when you're reading the source code, it tells you how to use the function, but it doesn't give you any guarantees at all. One thing that could give you some guarantees is if you assert it on the type of every single argument and of the return type every time this function is called. So I can assert on A, B and C that they're integers. I can do my business logic inside the function.
07:21
And then I can assert on what the return type is, and then finally return it. We don't usually do this either. What we usually try to avoid this for is because every assertion here is just a little bit of overhead, right? It's another line of code we have to run. It's an extra check. And actually this can also be wrong, right?
07:41
It's sort of dependent on whether the developer has written the assertion correctly or remembered to add the assertion to their function. So there's things that could go wrong here as well. And we don't do this very often. So what do we do instead? So instead in Python, we do something that we call duck typing, which is that if it walks like a duck and it quacks like a duck, it is probably a duck, right?
08:01
We rely on how the variable is used to sort of determine what type it should be. And so for some examples, in each of these, you can kind of guess what the variable bar is based on what is being done with it. So in the first one, you can tell we're iterating over it. So it's probably like a list,
08:22
could be a string though, it's hard to tell. In the second one, we're comparing it to zero with a greater than operator. So bar is probably some kind of number, like an integer or a float. And in the last one, we're calling it, right? But it's kind of ambiguous. In the last one, it could be a function, it could be a class.
08:41
I don't know what I'm gonna get back for foo in each of these. So it could be anything. And yeah, the ambiguity here, if we wanted to reduce the ambiguity, is what static typing would give us. So static typing means that the variables and the return types and the argument types of the function are defined and they will not change.
09:01
So there are actually lots of statically typed languages. I wanna show you some examples real quick, just so you can see what they look like. So this is C. This is the same from the key function, but written in C. So you can see that it's declaring int for the return type and int for all the variable types. This is Java.
09:20
It's pretty obvious if you use Java before, because Java has this public static int incantation at the beginning, but also declares argument types to be integers. This is Rust. So Rust has really fine-grained control of the integer type. So that's an unsigned 8-bit integer that it's accepting and returning. And this last one is TypeScript. So in JavaScript, JavaScript doesn't have static types,
09:42
but there's a variant of it called TypeScript. And in JavaScript, all numbers are the same thing. They are in number. So in TypeScript, there is only the number type. So everything passes argument and this function is the number type. So we can sort of put languages into two categories, dynamic and statically typed. You can see that Python, right in this slide,
10:02
is in the dynamic category and things like C and Rust and Java and TypeScript are in the static category. But we have to put a little asterisk here because Python is kind of an odd duck and kind of we can do static typing with it as well. And technically Ruby is gonna get something very similar to Python at the end of this year, I think, last time I checked,
10:21
but for now I'll leave it in the dynamic column. So like I said before, Python is dynamically typed, but can optionally be as statically typed as you want it to be. So this wasn't always true. And the story of how Python became a language that can optionally be statically typed is also kind of the story of static typing at Dropbox.
10:42
So Dropbox is a large Python shop that use a lot of Python, a lot of Pythonistas work there. And there were some things sort of in their journey from going from untyped to typed Python code that led up to static typing as we know it in Python today.
11:01
So I'm gonna give you just a quick overview of everything, sort of the progression of static typing and how Dropbox is involved in that kind of thing. So in 2006, we have a PEP 3107. This came out in Python 3, and this allowed us to do something called function annotations. So it allows us to take a function like this and add basically any metadata that we want
11:24
to argument and annotate the arguments and return values. So thing to know here is that this has zero effect on the execution of the function, but what it gives us is a nice little attribute on the function of the annotation.
11:40
So it will actually evaluate the annotations, put them in this nice little dict based on the variable and the return type. I'm not sure what would happen if, yeah, you were passing an argument named return. I guess maybe that's probably not frowned upon, but yeah, you would get this annotations dict and that would,
12:01
anything that was sort of putting together this function would have access to these annotations. As this is interesting, and the PEP included a bunch of ideas about what this could be used for, and they all kind of boiled down to typing and then maybe some other stuff like documentation. So this allowed us to write a function like this
12:22
if we wanted to do evaluate typing with it. I could, as the annotation, pass this class or the keyword that represents that class, and then when I access the annotations, it would tell me what I had written in my source code as the annotation for those variables and the return type. But that's all it gives us.
12:40
It doesn't give us a way to evaluate whether this function was being used correctly or whether these return types were actually being returned. And it only gives us a way to annotate functions. It doesn't give us a way to annotate any variables or anything that might be used within the function or outside the function. So around this time, Yucatec Tassolo was working on his PhD research
13:03
at the University of Cambridge, and his research was about the unification of a statically typed and dynamically typed language. And he wanted to use the same language for everything from a tiny script that doesn't need static typing to a sprawling multimillion line code base. And he was also focused on the gradual growth.
13:21
He wanted to be able to slowly migrate from an untyped prototype to a statically typed product, everything from take that little script and slowly migrate it to something that was large and statically typed. And this is the idea that you basically don't have to do it all at once, right? He wanted to be able to make static typing completely optional. So he published his thesis in 2011,
13:43
and it said something basically along these lines. He found that adding a static type system to a dynamically typed language can be a really invasive change would require coordinated modification of the programs, virtual machines, development tools, basically everything that the language touches would have to be changed. But he found that adding an optional,
14:01
optional, plugable type system would not affect the runtime semantics of the program and could be added to a language without affecting the existing code or tools. So this sounds really great. It sounds great for Python because we're already set as a dynamic language. Being able to statically type things optionally makes a lot of sense. So at 2013 at PyCon US,
14:21
he introduced something called MyPy. So if you've heard of MyPy before, what he introduced was not exactly what you might think of MyPy. At the time in 2013 when he gave this talk, MyPy was described as a experimental variant of Python that supports writing programs that mix dynamic and static typing.
14:41
So in his research, he wasn't able to use Python as the language that he was using to do his research. And so instead he created his own sort of variant, which he's doing research, so it sort of makes sense that he could create a variant just to sort of prove his theories. His variant looked like this and he actually called the variant MyPy.
15:01
And the variant looked like this. You can tell it kind of looks like Python if you squint at it, but there's some other stuff happening here. Like you can see where the function fib is being declared as an integer and the argument type kind of looks like a function annotation that we were talking about before. So it kind of looked like Python, but wasn't Python, but you could compile it to Python.
15:21
And so the issue was that even with the function annotations, Python couldn't support everything that was necessary to be statically typed. And so what happened? He presented this at PyCon and he talked to Guido afterwards. And Guido said basically, let's drop the custom syntax, let's drop the variant on the language and let's just do this in regular Python 3.
15:41
So MyPy also included a type checker for the variant. And that is actually what we think of as MyPy today. And that since it was now modified to check Python itself. So in 2014, we got PEP 483. This is a theory of type hints. And this is basically Guido putting down his ideas about how static typing should work in Python.
16:01
And his idea is sort of aligned pretty well with what Yuko was working on. So he said that typing should be optional. Adding annotations shouldn't affect the runtime of the program, shouldn't get in your way. An annotated function should behave exactly the same as an unannotated function. And I think this was probably had a lot to do with the lessons we learned from the Python 2 to 3 migration. We wanted a adoption of static typing
16:22
to not be a breaking change, not require a huge migration and that kind of thing. He wanted it to be gradual. And this allows us to annotate only one part of a program or even just one function of a program and sort of leverage the aspects of both dynamic and static typing together. He wanted to add variable annotations so we could annotate more than just a function.
16:42
And so that means that we could do something like this instead of having our variable bizbaz be unannotated, we could add a comment like this called a type comment. And this sort of gives us a type annotation for that line without changing the Python syntax. And he wanted to be able to support type hinting for Python 2
17:01
because function annotations only existed in Python 3 at the time. So he wanted it to be possible for it. Even the people stuck with Python 2 to continue to be able to adopt static typing. So that means that in Python 3 we could write these nice function annotations but in Python 2 we could fall back onto these type comments even for the function definition and that kind of stuff.
17:23
He introduced some special type constructs which were sort of building blocks that we could use to define types. So that adopted all the existing types like int and float and then created some new types that come from the typing built-in module. Like any, any would be a wild card for matching any type.
17:41
Union would combine two types together into a single type. Optional is the union of none and basically any type that you want, tuples, subtypes for collections, that kind of thing. So that would let us write a function like this. Once we have special type constructs, we could say that the last argument to this Frob Mckay function could be an integer
18:00
or it could be a float but the first two have to be integers. And then we could similarly define the return type to also be the union of int and float dependent on what was passed into it. It also defined some container classes. So these are things like lists and dictionaries. So we can type the keys or values of a dictionary, for example. So like I could define a list that contains all integers
18:22
and trying to append a string would fail. I could define a dict that has a key of a string value of an integer. And similarly trying to go against the typing would fail the type checker. It also introduced some generic types for when classes and functions behave in a sort of generic way.
18:40
So we could do things like this. Just say that work accepts an iterable, give us some aliases as well. So if we wanted to, we could union all the numbers together into a single number class and be more like JavaScript. And next in 2014, we got type hints. And this was given to us in Python 3.5 which was the least with that support.
19:00
We got syntax for variable annotation. So that let us go from the comments style syntax to pure inline Python where we can annotate variables. We get initialized variables with types without actually having to give them a value. Similarly for classes. In Python 3.6, we got that 526 support which almost had everything we needed. Last thing that we needed to finish the puzzle
19:21
was a type checker. So the difference between type checkers here is static and dynamic. So mypy at this point had fully transitioned to a static type checker. That means it's gonna check all of your code at rest. And it works kind of like this. You would install it from pip. You would create a Python file.
19:40
Okay. And you would define a Python file and then run mypy on it. And it would tell you when you're using types correctly or incorrectly. So at this point, there are actually lots of static type checkers and dynamic type checkers as well which would check your types at runtime. So basically all the big Python shops
20:02
had their own type checker and still do actually. So Dropbox basically owns the development of mypy. Google has a tool called pytype. Facebook has py or Microsoft has pywrite. And actually some editors have type checkers built into them like PyCharm. And then yeah, there's a bunch of dynamic type checkers as well. I think those are not quite as popular
20:20
because they do add a limitation at runtime. So one of the questions I get a lot about this are the differences between the static type checkers. Cause if they're just implementing the standards, like what could possibly be the difference? Maybe one's a little bit faster than the other. So I'll talk about the big sort of philosophical differences
20:40
between mypy and pytype, which I'll call cross function inference and runtime lenience. And these are sort of comes down to a difference in philosophy about the behavior. So for cross function inference, here's an unannotated file. And if I were to run this in Python, I would get a type error, right? Because what I'm trying to do here is concatenate a string with an integer
21:00
and that would fail. So just executing Python, I get a type error. If I run this through mypy, it actually succeeds. It doesn't tell me there's anything wrong here. If I run it with pytype power, it will give me an error. And the problem is that mypy doesn't have the ability to infer types across multiple function calls and pytype does. So pytype says, well, that's gonna be a runtime error.
21:22
We need to raise an exception or fail the type checker here. Similarly, another difference in philosophy is sort of whether functions that succeed at runtime should be type errors or not. So in Python, I can annotate a list to contain all these strings, but then it's totally valid to append an integer to it.
21:42
That won't actually create a type error in Python. And so if we run this, it works just totally fine. If we run it with pytype, it says there are no problems. This won't create a runtime type error. Mypy is a little more strict though. It will say, well, you define the type for that list to be a string
22:03
and you're trying to put an integer in it. So that will fail. All right, some more questions. You might just be saying, all right, why? Why and when should we use static typing? So first I'll talk about when you shouldn't use static typing, which I think is basically never. I think static typing you should just use at your leisure
22:21
or as liberally as you want. You should be able to experiment with it. One thing I'll note is that static typing is not a replacement for unit tests. And there is a bit of similarity here. Sometimes unit tests end up looking a lot like type checking. You sort of pass certain things in and assert on the output of the function, whether it errors or succeeds. But really unit tests are just a bad type system.
22:42
In reality, you probably should do both. So when should you use static typing? Basically use as much as possible. Use it whenever you can. You should definitely use static typing when you're millions lines of scale. So if you're Dropbox or Google, you've probably already invested a lot in static typing in Python. And actually Dropbox found that at their scale,
23:03
dynamic actually was a liability for Python. It made it really hard to understand how functions and how a code base would work and began to impact productivity. So all those companies have invested a lot of money in the work that was already done here. And the lack of typing,
23:20
you can think of it as a liability once you get to be that big. Made a little handy graph. So the time to start thinking about static typing is not when you're the size of Dropbox or Google, but sometime before that. So you're probably here. This is when you should start thinking about adding type annotations. Here's when you'll probably actually do it, but that's okay. You can gradually add it as you go.
23:43
You should also use static typing when your code is confusing. So let's be honest, we've all written confusing code before. Some people like to say that annotations are a machine verified documentation. That's true. If you feel like you need to document a confusing function, specifically the input output types of it, for example, you should probably just statically type it
24:00
because that will be just as clear. And then you can do static analysis on it as well. You should also use static typing when your code is for public consumption. For example, if you're gonna put it on IPI as a module. So adding type annotations helps third-party developers that wanna use your module know how to use it. It also lets IDEs do auto-completion and tell you how to consume the API.
24:21
And then if your users are already using static typing in their code base, and they wanna pull in something from your library, they will absolutely love that you can support static typing as well. Another place that you can use static typing is before migrating or refactoring. So before you make a big change, go and add some static types, move things around, and see if any of the typing breaks.
24:41
That's probably a bug. And finally, you can use static typing just to experiment with static typing. It doesn't hurt. It's totally painless. And it's just be a fun way to learn about a new part of Python. So to wrap up, how to use static typing in just five easy steps. First, you have to migrate to Python greater than or equal to six. Now, this is actually optional.
25:01
You can use type comments in any version, but let's be honest, you should migrate to Python 3 anyway. Install TypeChecker locally. I don't care which one it is, but install it and integrate it into your editor so that it runs automatically when you write or save a file. And then you can start optionally typing your code base. Start with the most complex function or the easiest to understand function.
25:21
Don't try to do it all at once. Remember, it's intentionally a gradual process. And pick sort of critical areas and start there. Second to last, run the TypeChecker with your linting, put it in CI and have it just run there anyways, assuming that you have CI. And finally, convince all your coworkers to join you. So if you need help convincing them,
25:41
feel free to send them my way. Thanks everyone to the talks. And I wanna give a quick shout out and thank you to the organizers as well. This has been really amazing, seamless online conference and they absolutely deserve your thanks as well. So thank you everyone. Thanks for your attention. Absolutely, thank you so much.
26:01
I am supposed to be able to play this. I'm gonna open the door and let the audience in. So I have one question here. Oh wow, actually this has gone up to five in the last few seconds, but we don't have time for five. We'll do as many as we can. So anybody, if we don't get to your question,
26:23
look in Discord for talk static typing. You've talked to Dustin, there's more. But let me see here. So someone said, is there any tool which can build API docs with return types of each function by extracting static type annotations from your Python code?
26:43
So you're saying automatically building documentation from static type? Annotations? Yeah, I think there's some stuff that exists and definitely there's a lot of the documentation tools now will take into account whether you have statically typed functions. You don't need those long doc strings that I was showing
27:01
for in order for your API documentation or your module documentation to pick up and show what the expected values are for this one. So I haven't actually used any of them personally, but yeah, I imagine that some of the more prominent documentation tools definitely should be supporting that. Okay, Francisco asks, how can one combine type annotations
27:22
to perform static type checks with mypy with detailed doc strings? So it's kind of along those same lines. Oh, so you already have detailed doc strings and you wanna add type annotations. Yeah, that's a good question. I'm not actually familiar with a way to do that. So it's sort of, I guess there are type checkers
27:40
that check doc strings and there are type checkers that check static typing annotations. I'm not sure if there's any that do both. I'll try and find out and I'll let you know in the chat. Someone says, what about mypyc? Is there a future for compiled Python using type hints? I think there might be. I don't know a whole lot about mypyc,
28:02
but yeah, definitely I can connect you with folks that are working on that. And yeah, there's some interesting developments there, I think. All right, well, once again, thank you very much. Thanks, great to be here.