Python Typing - Type Hints & Annotations

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello everybody and welcome to another youtube video in today's video i'll be covering type hints and annotations in python along with a bunch of content from the typing module now what this will allow you to do is add types to your parameters to your variables to your return values from functions such that you can actually have better documentation of your python code your autocomplete works better and any other people that are reading your code can very easily see what types are expected of certain parameters method calls whatever it may be regardless you will see all of that as we get into the video after a quick word from our sponsor before we dive in i need to thank ltm designer for sponsoring this video ltm designer is the world's most trusted pcb design system that enables engineers to effortlessly connect with every facet of the electronics design process ltm designer has used 35 years of innovation and development to create a truly unifying design environment that makes it the most used pcb design solution on the market ltm designer provides an intuitive and powerful interface that lets you design pcbs rapidly while interacting and collaborating with your mechanical designers the interface provides a photo realistic 3d environment collaboration and synchronization with tools including solidworks ptc creo and autodesk inventor realistic rigid flex designs multi-board assembly and much more ltm designer is the most popular ecad tool and electronics design software and you can get started with it today for free by pressing the link in the description and registering for a free trial thanks again to ltm designer for sponsoring this video and now let's dive in alright so let's go ahead and get started in front of me i have the official documentation for the typing module in python this is a built-in module you don't need to install it and as it says here this is new in python version 3.5 so you do have to use 3.5 or above for this to work for you now i'm going to be using python version 3.8 in this tutorial in python 3 9 which is the newest release of python they do have some very small differences and kind of additions to this module i'm not going to cover them because they're pretty insignificant but i just want to mention that in case any of you were wondering now what i've done for this video i've read through this documentation i've kind of picked out the most important and most common things that you would use and i'm just going to cover them here so if you want the full list of everything you can do which is very complicated in advance then you can feel free to read this i will link it in the description anyways with that said let me just quickly talk about why you would want to do some of the things that i'm going to show you so really all this is is documenting your code we're going to be adding types to our parameters adding types to our return values but this doesn't actually change the functionality of your python code it won't make it so that if i don't pass a string here the program crashes that's not going to happen all of this is just documentation you can kind of treat it as comments and the point of that is just to better document your python code make it easier for other developers to understand what to pass to your function or methods and to make it easier for your autocomplete or linter to do its job so if you do this you add types to all of the python code that you write your autocomplete will be way way better and lastly i'm going to show you actually pretty soon here how you can use what's known as a static code analysis tool with these types to tell you if you have type mismatching so this is a way that you can kind of catch errors before running your code it will tell you hey you passed a list of strings when it was expecting a list of floats anyways just wanted to mention all the stuff we're doing doesn't enforce that these are the types these values need to be it is simply for documentation purposes anyways let's get into it here and i will show you the first example of type annotations alright so what i'm going to do here is make a variable i'm going to call this x and i'm going to store a 1 inside of here now in python this is obviously completely valid code we don't need to define the types of our variables of our parameters our functions whatever we can just write it like this x can store one and later on in my program x can store something like tim that's completely fine however in a lot of other programming languages that are statically and strongly typed you need to actually declare the type of a variable before you can assign a value to it and then that variable can only hold that type throughout the entire program execution so what you would have to do is maybe something like this and x equals one and this means x is storing an integer it can only ever store an integer and if i tried to store a string here then my program would actually crash or not even compile but in python since it's dynamically typed we can just do x equals one and then later on we can say x equals tim and this is fine however if we want to add a type annotation or a type hint to this we can do the following we can add a colon then we can add what type should be stored in this variable so i'm going to say x and then string now yes i know the correct type would be in but i'm just showing you that we can do this now watch when i run the code i don't get an error the reason i don't get an error is because this is not enforcing that x is going to store a string it's just saying hey x should store a string so that's what i meant with this is simply documentation this doesn't change any of your python code's behavior it just adds an annotation that's what it's called a type hint to this variable saying hey it should store a string great so now what i'm going to show you how to do is use a static code analysis tool to actually look at your python code examine the type annotations and see if you have mismatches with your types so the way you do this is you need to install the type annotation sorry you need to install the static code analysis tool so you have to go pip install and then my pi like this now you do this in terminal or in command prompt depending on your operating system and if pip doesn't work for you you can try pip three if that doesn't work for you i'll put two videos on the screen that hopefully should fix this command for you anyways i'm gonna do pip install my pi we can see i already have it installed and so all is good now if i want to use my pi to run a static code analysis check on this python file what i do is i type my pi and then i need to put the path to my file so mine's on my desktop and then slash and then this is going to be let's just type it out python underscore and then typing dot pi like that now when i run this give it a second here notice it shows me it found one error in one file it says incompatible types in assignment expression has int variable has type string so this is telling me hey on line one here we found a mismatch in types so you should go fix them so that's what the static code analysis tool is again another reason why you would actually add the types because you can use a tool like this there's a bunch of other ones as well i'm just showing you one example of them to tell you if you have any mismatches great so now that we've seen that that is the variable annotation i'm going to show you how we do this with functions which is much more useful so i'm going to say define a function let's just say add numbers like this and maybe we want to take a b and c and then we want to return the sum of a b and c so let's do a plus b plus c like this well now i want to add my types to this so just like i added the type for my variable for each of my parameters i will say that these should be an int so i'll go int and like that okay then i want to add the return type of my function so to do that i actually just do an arrow so this is going to be a hyphen and then i guess the greater than sign and then what i will do here is put int like that now this is saying this function is going to return an integer and there you go i have just added types to my add numbers function now let's do this add numbers one two three we can store this in x and print it out and i'll just prove to you that everything is working completely fine there you go that's really the basics on adding your annotations to functions and adding their return type now i will note if your function is not returning anything so maybe instead we're just printing a plus b plus c in that case we don't need to print x anymore then what we do for the return type is we just put none so all python functions by default return none if you don't return anything so you just put none here and then this is all good it continues to work all right so now that we've looked at the basics of function annotations i want to show you some more advanced types that we can use so a lot of times you have some well more advanced or more complicated types that you want to pass as an argument to a function for example maybe we want to have a list that has a bunch of lists in it or maybe it only has three lists in it exactly and these lists all have integers inside of them well what is the type for that well the type for that is actually list list and then inside of list you would put it that's what the type would be but i'm going to show you that this actually doesn't work the way it is right now so if i try to make this the type let's just go x colon equals that and let's just make this equal to a list and i run the code you're going to see we get type object is not subscriptable that pretty much means this here which is a type object i can't subscript it so what i need to instead is import the list object or the list type from the typing module so i'm going to say from typing import like this and then list with a capital l so now that i've done this i'm going to change this to be a capital l on my list and notice that this is now completely fine so if you want to use list as a type and you're using python version 3.8 or below then you need to have list with a capital l importing from typing now i'm saying again this is list list int which means we would have something like this one two three four and that is a valid type and in fact if we want to check that let's just say my pie and then this is going to be desktop like that slash and then python underscore typing dot pi uh let's see what we get no issues found in one source file great so now that we've looked at that let's look at a few other types with some different built-in python data types so we just covered list but let's change this now to use a dictionary so if i'm going to use a dictionary i need to specify the key and the value type so i'm going to say string and string like that and i'm going to make this equal to and let's just go with a colon and then b like so all right let's see if this is going to work actually if i run my code and notice we get the same error type object is not subscriptable i can't just do this so again what do i need to do i need to import dict like this from typing so now if i do this with a capital and i run the code all is good and if we run our my pi command let's see no issues found in one source file so that's how you would do it for dict now if you want to do it for set the same thing is going to happen so you need to import set like that now we would go with set and then we would just specify what type is in the set in this case it's just going to be strings so now we have a set and all is good perfect so that is set that is sticked we could also cover bool if you want to do bool then while you just write bool like that pretty straightforward and then string obviously we saw as that and we know is that and float we know is that great all right so now that we've looked at those let's look at an example of creating our own types so a lot of times what you want to do is have a very complicated kind of type like this and you want to simplify it by just giving it a name so a good example of this is something like a vector okay so what i can do is the following i can say vector it doesn't matter if i have a capital or not but this is kind of convention sorry is equal to and then this is going to be a list and this list is going to contain floats okay so i'm just going to say this is my vector type so now that i've done this i can use vector and wherever i use vector list float will kind of be replaced there right or we'll be substitute in for vector so if i go define let's just make our function foo let's say v colon vector this is completely fine and then this could return a vector like that let's just print out v okay now watch if i start typing foo notice it's giving me the type completion here right saying v list float gives me list float so i have vector here but it's replacing it with list flow so hopefully that kind of makes sense but you can do this right you can just store a type inside of a variable and then use that variable as that type this is very nice when you have super complicated types let's make another one let's say vectors maybe vectors is equal to a list of vector objects again this is now completely valid our vectors type is just a list that contains a bunch of vectors which is the type that we defined up here so we can use our own types in these now let's just do another example i probably should just left what we have before let's go v and then vectors like that and then we'll return a single vector and let's just go pass and let's call the function and notice it tells me list list float and then list float so there you go that is how you make your own custom types they can store whatever you want in fact you could even do something as simple as like vector equals float i don't know why you do that but you could do that all right so moving on from this i want to show you a few more types that we can use now these are kind of more special types or edge case types but you definitely do need to know them all right so let's make a function let's call this foo and let's have this function taken an optional keyword argument something like i don't know let's go with output is equal to false okay so if i was going to add the type for this then what i would do is the following i would just say output and then i would go with bool like that is equal to false if i run this everything is totally valid no errors at all that's fine now when i call this foo function i can call it with or without output the thing is this is optional and right now this type does not specify that this parameter is optional now if i do run my static code analysis tool you will see that it's not going to give me an error here if i were to try to call the foo function without this parameter without output this would be fine i wouldn't get an error but to make this the most correct type that it can be you need to specify that it's optional so the way you do that is you import optional from your typing module and then you specify optional and then the type this should be so optional and then bool this just says okay this is now an optional parameter you don't have to pass it when you call the function anyways that's the type i want to show you optional pretty straightforward now other than optional we have another type this is the any type now the any type is very straightforward but if you are willing to accept anything then you just use the any type so let's say output could be equal to anything let's now make it mandatory then i would just put any like this and now anything is accepted inside of there now writing this is the exact same thing as just doing this because if you don't give it a type it's assumed it could be anything but this is just being more explicit you're saying yes this is intended to actually accept anything i didn't just forget to add the type that's kind of why you would put it here great so now that we've looked at optional in any i want to talk to you about sequence so a lot of times when you're writing a function in python you want one of the parameters to be anything that's a sequence you don't care what type of sequence it is it could be a list it could be a tuple it could be a different type of sequence you don't care you just want it to be a sequence so if that's the case you can use this special type known as sequence now the reason you need this is because there's no way to specify oh this should be a list or this should be a tuple but if you use sequence you're saying okay both the tuple and the list count as a sequence and so i'll accept any sequence and i'll show you that with sequence you can also specify what type the sequence should be stored so let's go here and let's say maybe we have a let's just call it seq like that standing for sequence if i wanted to give this the correct type i would say sequence and then whatever is going to be in the sequence so like string okay then what would be valid to pass this would be something like a tuple so i could pass a tuple full of strings let's go a b c like that and then let's just do this exact same thing but let's change this to a list and then we'll run our static code analysis tool and we'll see if this is causing any problems so let's save that let's run my pi notice we are all good however watch what happens if i go and now i try to pass uh let's just pass a int pass foo with one actually i don't want to run the code i want to run the static code analysis notice we get this error it says foo has incompatible type int expected sequence string now let's actually just see what happens if we pass a string because a string might be considered a sequence i'm actually not sure about this one okay so a string actually is a sequence as well i believe this is anything that can be indexed that would count as a sequence to do one more test here let's try a set so one two three i'm not sure if this one will be a sequence or not yes okay so it's not a sequence the reason it wouldn't be a sequence is because we can't index this set and it is not ordered hopefully that kind of makes sense but that is the sequence type again you use that when you want to accept anything that can be indexed so you're looking for a string you're looking for a tuple you are looking for a list all right so now i just want to move on and quickly talk about the tuple type which is something we haven't covered and works a little bit different than list so if i want to give the correct typing for a tuple what i need to do is actually specify what is going to be stored at every single position in the tuple just watch if i say x colon tuple like this what i can do is say okay this is a general tuple object so in this case i can put anything inside of here and it's fine so if i go with like hello and then let's run our my pi here notice this is completely fine however if i do want to specify what's inside of the tuple then what i would need to do is import tuple like this and then go with tuple now usually if we just had ins inside of our tuple we might imagine we could do tuple ins like this and this would be fine however if i save this and run my pie notice we get an error it says that the expression has type tuple int int and it found tuple int so what that means is we actually need to specify what every single element in the tuple is so int like that and now if we run my pi that should be good all right just want to quickly cover tuples because they're a little bit different than lists and i showed those previously all right so now that i've covered the tuple type what i want to cover is callable now callable is what you use when you want to accept a function as a parameter this is actually very common especially if you're doing some more advanced like not beginner programming you want to accept functions as a parameter anyways the way you do that is using callable so we need to import callable like that from typing and let's say that we want this foo function to accept a function and it's just going to call this function with let's say values 1 2. well the proper type for this function would be callable and then what i would need to do here is to find another set of square brackets and define the parameters that the callable function is going to have as well as the return type so i would say int and then int like this now what this says is okay this callable function that you pass to me has to have two int parameters and has to have an int return type now let's say it had an optional in parameter then you would go optional ins like that right you would add that as the third value here inside of call so hopefully that kind of makes sense but let's look at an example so let me define some function let's just call this add let's take x y x is going to be an int y is going to be an int and then what is this function going to return well this is going to return an int like that and then what i would do here is oops that's not what i meant to do i would just return x plus y now i forgot i do need to specify the return type for this function as well so i will make that none and now if i call foo i can directly pass the add function and if i run my pi we shouldn't see any errors we are all good however let's see what happens if i remove one of these parameters so if i remove the y parameter and now i run my static code analysis notice we get an error because this function does not have the correct parameters inside of it great now in the same way that we can do this for a parameter we can do this for a return value so maybe what i do instead is actually this let's copy this let's define this function inside of here and then now we want to actually return a callable so i'm just going to copy this here and make this the return type so let's do this let's just make this empty and then return add like that so i'm sure this is a little bit complex but what i'm doing is adding a nested function inside of this function and now i'm saying okay i'm going to return a new function this function well it's callable it's going to have two parameters and its return type is going to be int and if i run my pi here notice we are all good great so now that we've looked at that i will quickly mention that this also works with the lambdas as well now you can't actually add type hints for lambdas at least not very easily but if you want to return a lambda function then you could just do this lambda x y and then let's just return x plus y now since i didn't specify the types and again it's very difficult to specify the types for the lambda uh what you could do is this i'll run my pi and notice all is good now if i wanted to specify the types of the lambda i'll actually just show you how you would do this you would make a variable so let's go with funk colon then you would specify its type as callable int int ins in this situation make it equal to the lambda and now you could just return function like that and this would be fine now you specify the types for your lambda function if this looks super complicated to you don't worry about it too much just for anyone wondering this is what you would do if you're going to return a lambda all right so now we are almost done the last thing i'm going to cover is generics now this gets a lot more advanced than what i'm about to show you here but i'm just going to give you a general introduction so let me import something called type var here now i'm just going to go through an example then i'll explain what has happened i'm going to say t is equal to and this is going to be type var with t now this is the actual name of the type so usually you just match it with the variable name but you could make this something different if you wanted to anyways what i'm saying is that this is going to be a generic type now a generic type is something that's kind of a placeholder i'm saying okay i don't know what this type is actually going to be but i'm going to call it t so that i can consistently reference it throughout a function or class or whatever it may be again i'm sure this makes no sense right now but let's just do an example i'm going to say define and let's say get underscore item okay now what this is going to take in is a list so i'll say lst is colon and then this is going to be list at and then t okay so a little bit weird but list add t and then we will take an index this will be an int and we will return t okay now let's just return lst at index all right so this is a good example of generics the way this works is t is a placeholder variable i'm saying i'm going to accept a list this list can have any element inside of it so it could be an int it could be a float could be a string and any number of ins float strings whatever but they have to be the same type that's the point of this t is i'm saying okay i don't know what type is going to be inside of the list but i'm going to represent it by t and i'm going to assume that everything inside of the list is the same type t then i'm going to return t so whatever was inside of the list wherever that type is that's the type that i'm going to return so that's the point of doing this is you're saying all right i want this to be a flexible function that works for any type so anything inside of a list but to properly do my typings here i need what's known as a generic again they go into much more depth than this in the documentation but i wanted to introduce this to you because for most of you this is probably all you need but you can actually create a generic class you can create all kinds of very complicated generic types and with that said i think that wraps up pretty much everything i need to cover in this video i apologize if this was kind of all over the place i'm definitely no master at this typing system but i wanted to give you guys an introduction and i feel like what i covered here is probably about you know 95 of the average use case of most people again the real advantage of doing this is that you have documentation for your code your autocomplete and your linters are going to be better and if you're working in a large code base it's going to be way easier for other people to determine what is accepted in your function and if that was intended or not right just like we had this any type we're specifying explicitly what we are accepting just so people know hey this was not a mistake i do actually want to accept say any value inside of here hopefully you're getting the point regardless with that said i am going to end the video here i hope you enjoyed if you did make sure to leave a like subscribe to the channel and i will see you in another one [Music]
Info
Channel: Tech With Tim
Views: 25,789
Rating: undefined out of 5
Keywords: tech with tim, typing module, python, type annotations, annotations, static code analysis, function annotations, list type, list, dict type, dict, set type, set, custom types, custom, optional type, optional, any type, any, sequence type, sequence, tuple type, tuple, callable type, callable, generics, python typing, python typing module, python code, python type hints, type hints, python annotations, python type, python type annotations, python type checking, python static code
Id: QORvB-_mbZ0
Channel Id: undefined
Length: 24min 46sec (1486 seconds)
Published: Wed Sep 29 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.