Python 3.12 Generic Types Explained

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
python 3.12 has introduced a new much better Syntax for generic types and since I'm a type junkie I obviously have to cover it in the video so today we're going to find out how generic types in Python work and what the advantage is over just using the any type let's dive in Python has had type annotations since 3.5 they were added with pep 484 now type annotations are great but you can make them more generic by using generic types and that allows you to have even more Precision in the types of objects that you're dealing with and you've probably already used them before if you're using some of the existing types in Python for example a list of integers or a dictionary mapping a string to another type for example let's say you have a function that's called process numbers and that gets a list of numbers and then for example also returns another list of numbers now the list type has a generic component because it allows you to specify what types of elements are in the list and by writing int between these square brackets behind the list type we now specify this is a list of integers and not of strings or booleans or anything else one of the reasons we expect a list of numbers of integers here is that we're doing some arithmetic operations which you know if we got a a list of random objects we wouldn't be able to do object plus one but you can also imagine that there are some functions that work with list that are generic let's say we have a process Elements which gets elements and that's a list of some type T and it also returns another list of that particular type T and then it might return the elements uh at uh odd indices for example and then it's simp simp L does this right so when you look at a function like this now let's ignore the type errors for a moment actually it doesn't matter what the type is of the thing that's in the list because we're simply returning the elements in the odd indices we don't care this function works for a list of integers it works for a list of FO bars it works for a list of strings it doesn't matter what is in the list the only thing we do is we return elements at the odd indices so it would be a Pity if we had to Define this function for every type of list that we're going to use we simply want to say hey this is for any element we don't really care about it we just wanted to return elements at all Ines we don't care what's in the list and this is where generics can be very helpful but how do we specify that this is in generic type because at the moment we're getting a t is not defined error well that's where in the past you had to use typ fars for so we simply write T equals typ far far T and type far is something that we're going to import from typing so now T is a generic type and we can use it in a function like so and the nice thing now is that I can create a list of integers like so and then I can do uh processed equals and then I want to do process elements and then we print the processed list so when I run this code then we're going to get this the elements at the odd indices which are actually the even numbers so that's slightly confusing but what we can do is now we have a my string list and then actually we can do exactly the same and we get as an output a list of strings now that you see how awesome generic type annotations are you probably want to use them more in your code but the question is where are you going to host your application and the answer is on the VPS by today's sponsor hostinger of course you got full rout access dedicated IP address they support multiple operating systems including various Linux distributions and much more the VPS is hosted using powerful Hardware such as nvme SSD storage and AMD epic processors and with KVM virtualization your VPS can benefit from separate resources which leads to better performance and stability there's a great Black Friday offer for the VPS KVM 2 plan at the moment for the 12 or 24 month subscription you pay only $6.99 per month that's a 63% discount and if you use the discount code iron codes you get an additional 10% off so don't forget to use that you start by selecting a location for your VPS so I'm based in the Netherlands so let's select the Netherlands and then you can choose what kind of VPS you want so do you want an OS with a control panel just a plain operating system or do you want to use a Content management system like WordPress I'm going to pick OS with control panel because for me that's a bit easier to manage so I'm going to pick Ubuntu then simply click continue now we can create a panel password we also pick a root password if you want to access your server remotely you can already provide an SSH key right in the setup process so here's my setup and now we simply click finish setup and in a few minutes your VPS is ready to go with 24 7 support from the team you'll never feel lost and with the 30-day money back guarantee you can try them out risk free click the link in the description to get started and now let's go back to the video now you might wonder why do we need generic types uh why can't we just use any right so let me show you what happens if you use any instead of generic types so first thing that I want to show you is that list the IDE indicates that list is a list of integers right makes sense because we're assigning it a list of integers now process elements gets a list with elements of type T and returns also a list of elements with type T so that means that if I pass it my list which is a list of integers then processed is also a list of integers and the IDE knows that because process elements has that return type right and here my string list is a list of strings process elements is called with a list of strings and then process now is a list of strings which the IDE also knows because of the type annotation used in process elements so that's very useful now if you were to use any instead of this generic type let me change that so we would simply do that and then also replace it there now actually we don't need the type bar anymore so you would say okay great right Works in exactly the same way except that's not true because now if you look at my list so that's a list of integers but processed is now a list of any it's no longer a list of integers at least not according to the IDE so that means we've lost a lot of information and same here we have the string list process elements gets a string list but it returns a list of any so now we no longer know that process now has a list of strings even worse the specification of the type here doesn't say anything at all about how this list and that list is related perhaps process elements gets a little of integers and returns a list of strings we have no way to know that whereas with a generic type you can indicate no the type of the elements in the list that you put in is exactly the same as the type of the elements in the list that comes out and that's the main difference between using a generic type versus using any any just switches off type annotations basically it tells the type system to just ignore whatever the thing is because it can be anything now the issue with type fars is that it's kind of combersome to have to define a type far every time you need to use a generic type but with python 3.12 that actually all changes so I'm going to show you another example so here I have a before version where I'm still using the old style typ fars so here I'm specifying a typ far T just like in the previous example and then I'll come back to this later so here we have an example of a generic function that gets a list of items and then returns one of the items from the list and similarly you can also use type fars together with generics for classes so for example here I have a class box that's a generic class and that gets a type T and what this does it's just a container for an object of type T so we have an initializer where we store something of type T and then we have get item that gets that particular item and we have a set item kind of useless class but just to show how generic types actually work in Python but this is how you had to do it right right so you had your class and then you had to inherit from a generic type and then you could specify the actual type that's going to be used in the class itself that's how it worked and similarly now that you have the type for you can also specify a type alas like uh list or set for example and then you could say that it's a list of t or it's a set of T before python 3.12 if you want to have a generic type Alias like this list or set you need to add this part to the definition or won't work so in general this is how we were dealing with generic types before python 3.12 and then you can use them in a very simple way so we have an integer box so that works just fine we do get item that gives us an integer right because get item is generic and we know that type T is an integer and then we can print that and it also works for Strings we can even create a box containing a list it doesn't matter and here's a simple example of calling that generic function and then also here we know that the type of first item is of type in because we're passing it a list of integers then well let me run this it's not very interesting but this is what it prints that's before python 3.12 but with python 3.12 we no longer need type fars and there's also a much easier way of specifying type ls's and we also no longer need the generic type so let's see what that looks like so here's what that looks like in Python 3.12 so here's an example of a non-generic type elas the difference is that we write type in front of it so here's the before version we do it like that and the after version we have to type keyword in front of it and for a generic type alas we simply specify again using the type keyword we provide the name and then we write the generic type in square brackets behind it so list or set is now a generic type that is either a list of t or a set of T so it's a bit more coherent than how we had to do it before where here we could simply Define a type but here we had to specif CL ified as a type Alias it's the same now it's just type in front of it and then assign it the type that you want the Alias to be also we no longer need the generic type in a class definition so here's another version of that same box class so here let me show you what it looked like before so it inherits from the generic class and then that we provide the type T so that indirection is now gone we can simply write the class name and we write the type behind it in square brackets and for the rest it all works exactly the same way and for generic function we can now also Supply the type in square brackets behind the function name I'm getting some type error here I'm still encountering some issues with pyland in vs code unfortunately I think there are some bugs with how it detects generic types so I hope they will solve that soon but this is basically how you do it and then for the rest it works in exactly the same way as before so we can simply create our integer box and then inbox is of type box integer our item is an integer we can print that so it works in exactly the same way and when we run this then we also get exactly the same output obviously I must say I much prefer the newer syntax over the old syntax is much cleaner much simpler we don't need extra Imports to deal with generic types another useful thing that you can do with generic types is that you can Define so-called upper bounds so what that means is that you can restrict a generic type to a particular subtype here's simple example have a vehicle data class that has one member variable model simply displays a message when we call the display method and then I have a car and I have a boat and I have a third class called a plane actually this should be three big problem in the code right but now let's say we want to have a sort of registry of vehicles and we want to be able to add vehicles and uh display some information about those Vehicles so that's vehicle registry and I'm using a gen generic classes so this is the pre python 3.12 mechanism of defining a generic class and that relies on a typ far V and what I'm doing here is that I'm defining an upper bound vehicle so basically what I'm saying here is that if you have a vehicle registry generic class you supply the type of thing that that is the type that it relies on but that type is bound to vehicle so it has to be vehicle or a subass of vehicle you can't make a vehicle registry with something that's not a vehicle class and here's how you use that so let's say we have a registry here which is a vehicle registry of cars and then I'm going to add a few different cars and display car information now because this is a car vehicle registry I can't add a bat to it if I try to do that you see that we now get an error actually boat is incompatible with car you can't drive a boat on the road right but what you can do is Define a registor that accepts any type of vehicle by simply supplying this as a type and then we can add cars and boats so the upper bound is vehicle or any of its sub classes but if I now create a class coffee machine what I can do is create a coffee machine registry and use the vehicle registry for that because coffee machine is not a vehicle you can't drive a coffee machine so this doesn't work and that's what the upper bound does but defining the upper bound is again using typees which is a bit combersome but in Python 3.12 this also becomes a lot easier because here we have the same thing it's the vehicle class we have the vehicle subass I remov the coffee machine here because we don't need it but the vehicle registry is now a generic class based on V and V is bound to vehicle so that defines the upper bound so this works in in exactly the same way as the other example but now we're using python 3.12 generics again unfortunately I'm still running into a few issues here with pylons so the type reporting is a bit off but this is how it works and you can see that when I run this we get exactly the same output and by the way these upper bounds are pretty flexible so you can even specify multiple upper bounds by defining a twoo so for example here we have our vehicle registry which again is generic type but now we're using a tuple to tell it that you can create a vehicle registry of cars and of boats but not of planes for example or anything else so you can specify multiple options multiple constraints for your types using a tuple by the way if you like these types of nerdy type discussions you might also like my Discord server you can join for free by going to discord. ion. codes there's a lot of really knowledgeable helpful people there so Discord iron. Cod I've also put the link in description of the video so overall I like generic types quite a lot because they allow us for a lot of flexibility in how we Define our types and we can be pretty precise with how we Define them and you would use them mostly in container like situations where you would create let's say a list like structure or a dictionary like structure and you want it to be generic that's where generic types can really help a lot and that's as opposed to something like any which simply switches off type of system so that's quite different it also makes your code more reusable because you don't have to write multiple functions that do exactly the same thing with with just a slightly different type you can use generic types for that and by using the generics mechanism your IDE also still understands what type of things you're dealing with I do think there's always a trade-off though in how far you're going to go with this because if you really go in deeply you can get pretty complex types by using generics and upper bounds constraints and those kinds of things and it can become quickly pretty hard to understand what a type exactly is so you have to be also careful about how you do that and again also in type specifications design principles also rear their head right um You don't want to put a really complex type in a single huge type alas you might want to split that up into smaller type Ellas so you understand what is going on now Python and its ecosystem is still pretty opportunistic in how it uses type specifications they're not in all the libraries for example as opposed to language like typescript which really focuses on making sure the types are always there but that can also lead down a rabid hole where you're trying to fix some very esoteric type issue which actually doesn't really have any impact on the final application so you have to know sort of where to stop and not Dive In Too Deep because you're going to lose yourself but I'm really curious to hear your thoughts about this do you use generic types in your code how important is type Precision to you maybe it's not important at all let me know in the comments I hope you enjoyed this deeper dive into python 3.12 generic type system if you want to learn more about other features that python 3.12 introduced and there are quite a few some of them are quite interesting you should definitely watch this video next thanks for watching and see you soon
Info
Channel: ArjanCodes
Views: 58,679
Rating: undefined out of 5
Keywords: python 3.12, python 3.12 tutorial, python programming, new python features, python 3.12 new features, python generic types, generic types, any types python, python generics, python 3.12 generics, python 3.12 type, python 3.12 performance, python 3.12 changes, python 3.12 update, python 3.12 is here, python programming basics, generic types python, python any type, new features you need to know in python 3.12, generic types and collections, programming python, python tips
Id: q6ujWWaRdbA
Channel Id: undefined
Length: 18min 27sec (1107 seconds)
Published: Fri Nov 17 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.