here are 10 python Concepts that you really need to understand as fast as possible first concept is dynamic typing now python is a dynamically typed programming language and that means that whenever you define a variable its type can actually change later on so here we have a variable xal 10 because we've assigned 10 which is an integer to X the type of this variable is an INT however later in the program I can change this variable to something like a string and there's absolutely no issue with that this is one of the features of python that makes it amazing but also causes a lot of headaches let me show you what I mean so check out this example we have a very simple function where we add the values A and B which come in as parameters now even though we annotate these as an integer which is valid in Python you can Define what the type should be it's not actually enforced what that means is that it's okay for us to execute this code and python will run it no problem but while we run it we'll run into what's known as a runtime error let me show you what I mean if I run this you can see that we actually print out 30 which is the result of this first function call where we pass in two integers and then we actually get an error where it says you can only concatenate string not int to string that's because we've passed a string and an integer and again because python is a dynamically typed programming language it will allow us to execute this code but it will result in a runtime error I'm showing this to you because this is one of the major downsides of using python this Behavior can actually occur and when it does occur you'll get a runtime error which can be difficult to debug and to solve so when you're working in Python make sure you're familiar with this type of behavior and even if you add things like type hints or type annotations understand that they're not enforced and that the code will actually be able to run and you can get errors like this if you're not careful that's why if you really want to make your code bulletproof you need to check the types before you execute functions so what I can do is paste in something like this where I check if the type of a does not equal an integer I can also do this for B but in this case if I save the code now and I run you'll see that we get 30 and then we get invalid so we no longer have this type error because we've not allowed the function to perform this operation that depends on both of these values being integers so we'll dive into the next Concept in just one second but I quickly need to tell you about a fantastic resource I put together in collaboration with HubSpot which is a free guide on how to land a developer role in the world of AI now this draws on my over decade of experience and covers the top programming languages to master and the most most effective methods for learning them it includes the best practices for creating your portfolio and resume along with recommendations for YouTube channels and other resources to enhance your development skills I've left a link to it in the description and you can check it out completely for free personally my favorite part of this guide is the long list of resources like YouTube channels and websites that offer fantastic free ways to enhance your skills this content is really focused on how to set yourself apart and distinguish yourself in this AI era and offers essential insights to help you stay competitive as a developer like I said this is completely free and you can check it out from the link in the description from our video sponsor HubSpot so a massive thank you to them now the next important concept to understand is called mutability now in Python all of the types that we have are either mutable or immutable now your standard types like int float boole and string these are immutable that means that once you define them they can't be changed later on so if I do something like you know string is equal to hello I can't modify this string sure I can make a new one I can add something to it but this is actually creating an entirely new string object it's not modifying the existing string this is the property of an immutable type however if we have mutable types things like our lists sets dictionaries or even a python object that you define yourself these are mutable that means that you can modify them once they've been defined and you can do things like append to them and when I do something like append to my number numbers I'm not actually making a new list I'm modifying this list and changing its contents now it's important to understand this because when you use these types of objects that are mutable you can have some unintended side effects if you're not aware so look at this function here called mutation we take in some list and again this is mutable now inside of here what we're doing is appending 10 to that list and then returning LST which is the parameter that we have now you might imagine that after this function is called what's going to happen is we're going to make a copy of my number numbers and then we're going to have something like 1 2 3 10 being returned from this function now the question becomes what happens to my numbers the original list does this change or does this stay the same now because we're working with mutable types here when I run this you'll notice that it does actually change what happens when I pass something like a mutable type as a parameter to a function is we're not making what's known as a deep copy of this list object we're simply passing a reference to this list so when I make a change something like LST do append I'm not performing this change on a brand new list I'm modifying the existing list that was passed in so after this function is called what happens is we return LST which is really just a reference to this same list and now we have these two things the list after the call and my numbers being the same list with those mutations now another tricky thing can happen here if you use a mutable value as a default parameter so have a look at this I have something called mutation I have LST is equal to an empty list and then I have LST do append 10 now what I'm going to do is I'm just going to call the mutation function okay three times and then at the end I'm going to print out the result of the fourth call to my mutation function now if you've never seen this before you might think that we're just going to get an empty list every single time but watch what happens in the fourth call here okay so I'm going to clear this and run and notice that we actually get four tens inside of this list now the reason for that is when I use a mutable default parameter which is being used here this is only created one time it's not created every single time this function is called so we're using the same mutable list over and over and over again for every single function call which means by the time we get down to this fourth print statement we now have the list that contains all of the modifications we made previously so never use a mutable value for a default parameter and if you want to do this instead you can say something like LST is equal to none and you say if LST is equal to none then LST is equal to a new list so you actually Define a new one every single call and now you won't get that same behavior and if you run this you'll see that we simply get 10 now the next concept you need to understand is FST strings now FST strings allow you to embed python Expressions directly inside of a string and make it a lot easier to print out Dynamic content now look here you can see that I've simply put an F before some string it can be a multi-line string meaning you can have three quotation marks or you can just have the standard double or single quotes now when you place this F whether it's lowercase or uppercase it doesn't matter it allows you to write any valid python expression inside of a set of braces so I can write something like the name or an age and this will take whatever the value of this expression is in this case it's just a variable and embed it inside of the string it will actually automatically convert anything that might not already be a string into a string for you so in this case we have some int normally if we tried to add this int to a string we would get an error but the F string is smart enough to be able to automatically convert this into a string so I'll show you that this works just for our sanity here and you can see that we print this out and everything is valid now if we remove the F now we actually will not get that at all so if I run my terminal here and we do this again you see that I get the braces because it's not being interpreted as part of a kind of variable or an expression now we can do things like add we can call functions there's actually a lot of other things you can do with FST strings and I'll leave a video on screen right now that goes into a lot more details now the next feature to go over is slicing now slicing not only works on lists it also works on strings and topples and is very useful when you want to grab different sections of an iterable object or specifically a list string or tupple now notice that I have a list here that goes from 0 to 5 now in other programming languages if I wanted to grab a slice or a portion of this list I would probably need to use a method but python has some fancy syntax that allows us to do this so on my screen we have three examples of how slicing works so this might help you understand it but let me break it down for you a slice allows you to grab any elements between a start an end and a step very similar to something like the range function in Python now what you can do is you can define a start value and if you do this it defines what index you're going to start grabbing values from so in this situation we've started at one and that means that we're going to start at index one which has value one okay now you also have the ability to Define an end you don't have to which I'm going to show you in one second but you can now if you define an end you're going to go to that index but not include it so in this case we've decided we're going to end at index 4 which is element 4 but we're not going to include that in the output so again similar to the range function we will go to the stop but we will not include it so that's why we've grabbed 1 2 3 4 now we also have the option to include a step now the step is how many elements we should skip over as we grab elements from this list so if we look here you can see that I have colon colon 2 now what we've done is we've omitted the start we've omitted the end and we've included a step now all of these values are optional so you can decide what you want to include or not but when we do colon colon 2 that means we are going to start at the beginning of the list because we've not included it so by default we start at the beginning we've Not Included the end which means by default we're going to go to the end and include it which is important but we've included the step value which is two which means we're going to step over every first or every second index sorry so we're going to start at zero we're going to step to two we're going to go to two we're going to step by two and we're going to grab four and then when we step by two we're outside of the bound of the list so we no longer include any more elements that's the start end and step now as you've seen here you don't need to include them all so if you don't include the step by default you're going to be in the start end position if you don't want to include the end but you want to have a start and a step you can write something like this it's fine to have the two colons kind of combined together perfect ly valid and by the way you can use negative indexing here as well so if you look at this we're actually doing colon col1 now what this means is start at the beginning go to the end but step by negative -1 which is really just a shorthand to reverse a list in Python if you want to get crazy you can start doing things like you know go to -3 -3 means go to the third last element but do not include it in the list okay so negative 1 would be the last element -2 is the second last element neg3 the third last element so on and so forth and you can get creative in how you use these with this slice syntax the next feature that I want to go over is if uncore name uncore is equal toore uncore maincore uncore now this is a common convention in python and a lot of beginners have no idea how it works so I want to break it down for you but before we write that code I want to show you an example of why we need it so look here we have a helpers dopy file and in this file we want to call this great function okay whenever we run it we just want to call this function then we have this main.py file and this main.py file simply Imports this helpers file okay just Imports that module now let's look at what happens when we run both of these scripts and independently so if I run python helpers.com anything that's inside of this file we are going to run it that's just how the import works even if you're just importing a specific feature so even if I do something like you know from helpers so let's go here from helpers import and then I import the Greet function and I run main.py you see it still says this okay just a feature of python when you import code you run the entire script so why do we need this if uncore name equals uncore main well Watch What Happens so now if I add this convention and let's start by not printing out name what you'll see now when I run python main.py is that it no
longer prints out hello from my module the reason for that is that this checks if this python script is being executed directly this condition here will only be equal to true if we directly ran this python module now let me show you why that's the case because if I print the name here you'll see that when I run main.py you'll see here that the name is equal to helpers and that's because that's the mod module that we're inside of whereas if I run the helpers dopy file you'll see the name is equal to main so whenever you run a script directly the name variable in that script is going to be equal toore uncore main but when it's imported from something else it's going to be equal to whatever the name of the module or in this case the file is so this check just simply tells us are we directly executing this code if we're not then don't do this thing and the reason for that again is because a lot of times we want to import and reuse python code but we may not want to actually trigger something to happen inside of that script so I may have this script that does something really cool and I might want to actually execute it directly but then I may want to use one or two functions from it in another script and if that's the case I want to put this guard here so that I'm not executing something I don't mean to execute if I'm importing this from another script moving on the next feature I have for you is a bit of a weird one and this is the for else and actually while else syntax so a lot of people don't know this but you can actually tack on an else statement to the end of a for Loop or to a while loop in Python now this else statement simply acts as a check if we didn't break out or we didn't find what we were looking for within a for Loop so I'm going to show you a really quick example here we have numbers equal to 1 2 3 it's possible that we're going to search through this array or this list and we're going to try to look for something some kind of Target something like number equal to 5 now if we find it we can print out hey we found it and then we can break and typically when we break out of a for Loop that indicates that our work is done and we've achieved whatever the goal is that we need however if we don't break out of this for Loop and we exhaust all of the options that typically means that we didn't find what we're looking for and sometimes you want to handle that situation using something like an lse statement so that's exactly what this code is designed for if I go here and I run python main.py you see it says five was not found whereas if I add five to my list you'll see that it's going to print out found five and it doesn't execute this else statement now you might be asking why do we need this well it simply saves you adding a flag or a condition with in your for Loop so let me show you what I mean I can say found is equal to false and if I find five I can say find or found sorry is equal to true and then rather having the else I'm going to say if not found then I need to print five was not found so this is the alternative if you didn't use something like the four else sure it's not a ton more code but this is just kind of a better cleaner way of handling this situation without needing to add that flag variable now just like this works for four Loops it works for while Loops as well so it's perfectly valid to do something like while true and then you can search for something if a break occurs then you're not going to enter the else otherwise say you know didn't find okay so you can use an else uh with a well too as well as with a four and again it's for the condition where you did not break out of the loop the next concept to go over is star args and star are quarks now this allows you to accept an unlimited number of positional and keyword arguments often times when you're writing a function you don't know how many parameters you want to accept sure you can make something like a default parameter but if you want to accept something like an unlimited number of positional arguments or an unlimited number of keyword arguments you can do that by using this convention right here whenever you add a star args uh this actually means you accept any number of positional arguments which are these right here if you add a star star quars this means you can accept any number of keyword arguments and I'll show you an example of some built-in python functions that use this so it makes a bit more sense anyways if I run the code you can see that all of our positional arguments will be stored inside of a tupple and all of our keyword arguments will be stored inside of a dictionary and we can use them in the function as we please now if you're looking for a practical example of this look no further than the print function the print function in Python can take any number of positional arguments right it can take something like a string a few different numbers it can take no arguments can take any number of them that we want and if we look at print notice what it uses it uses the star arcs or Star values this just means it accepts any number of values and then prints them all separated by space out to the console there's all kinds of other functions in Python that use the star args and the starstar quar syntax and it's very useful when you want to make your functions more Dynamic and be able to accept really any anything that you want obviously be careful don't overuse this but in a lot of situations if you want it to be very Dynamic and accept any number of arguments you use this moving on we're talking about list comprehensions which are quite unique and useful in Python now on my screen I have a few different examples of them and I'll run through them quickly because I have many videos on this topic now have a look here what I can do is I can actually populate a list in place by writing something like this I can say x^2 4X in range 10 now now you need to have some kind of for Loop structure in this case I'm just looping through the range 10 and then whatever I have on the left hand side here is the expression that I want to evaluate for every single iteration of this for Loop now what this does is it generates a list of squares for me but we can get even more complex notice here that I've actually added an if statement so I can now have some kind of condition and I will only use this value X if this condition is true so if x mod 2 so if it's even I is equal to true then we're going to take X and then you can see that we get all of our events now we can do the same thing with a nested for Loop structure so I can say four sublist in nested for item in sublist and then I can take that item and I can grab or flatten a nested list by using this list comprehension same thing with something like the cartisian product I can actually take multiple values here for X in range three for y in ABC okay you get the idea now the reason I'm showing this to you is because obviously it's useful but this is actually significantly faster than writing code with a standard for Loop so if you just want to write out the same code but you want to use a normal for Loop structure where you're not doing it in place it will actually be slower the reason for that is python uses a c implementation on the lower level for list comprehensions so it's able to have less operations per cycle which means that it can just perform faster so if you actually look at these examples and you compare on very large numbers if you're generating you a huge list you'll see about a 20 to 25% speed increase by using list comprehensions so so it's definitely worth considering them especially if you're making something that is more kind of performance dependent so it's better to go with the fast approach rather than the arguably more readable approach by writing out the entire for Loop moving on we are talking about context managers and I'm going to show you the very classic example but it's an important concept to understand now let's say we're working with a file in Python and we have something like this and believe it or not this can happen what we can do is we can open a file using this open function and then we can write the file how however if you use this approach you need to explicitly close the file that's because if you don't close the file then it's still going to be held in memory and you can potentially have some memory leaks so what would happen if an exception occurs before the file can be explicitly closed well if that's the case then we would have some kind of resource leak because we never close the file and we're still storing that file handle so I'm going to show you an approach that fixes this problem called context managers I know this is a little bit of a trivial example but the point is to demonstrate what a context manager is so again just keep in mind in this situation I open a file I write to the file and then I need to close the file manually and if something goes wrong before I'm able to execute this line then that is potentially Troublesome now the context manager handles this for us when we use with which you've probably seen before we can say with open as F now what happens is this context manager manages the context of this resource and automatically cleans it up as soon as we exit the cont context manager now context manager as it kind of describes is handling what happens with a particular resource and you'll see this very commonly if you're using things like databases or opening again files so we open this file and then what happens is in the background based on how this is written it will automatically perform any cleanup operations for us as soon as we exit this indented block what that means is that even if we have an exception within this wi block here or anywhere else in our program it will automatically handle closing the file for us so we don't need to worry about it and it's just really the best practice I have entire videos on my channel where I break down the context manager more in depth and actually write them myself so you can look at the lower level implementation but I wanted you to quickly understand this concept exists and when you're using this with statement what you're actually doing is you're working within a particular context that is controlled by this statement or the context manager so will automatically handle what you're doing with this particular resource or at least closing it opening it all of the CLE up operations that need to happen behind the scenes now the last thing that I want to show you here is something known as multiple assignment and unpacking now this can actually go quite a bit further in Python I'm just showing you a few quick examples here so in Python you can do something like this you can say a comma B comma C is equal to something like 1 2 3 and as expected we can have all of the appropriate values associated with whatever we defined here okay so A1 B2 C3 but we can go a step further and we can actually use this type of syntax to unpack iterable object objects so something like a list a tle a string anything that's iterable and that we can access values at index by we can use this for so I can actually decompose or unpack this tupple into its individual components X Y and Z by saying XYZ is equal to something like my tupple and now we get 10 20 30 and with this same syntax we can actually perform inline variable swaps and I can do something like a comma B is equal to B comma a and now I've swapped the values of these two variables in line without having to manually create a temporary variable typically if you want to perform a variable swap what you would need to do yourself is you would need to say something like temp is equal to a you would then say something like a is equal to B and B is equal to Temp because you're going to lose one of the values when you perform these assignments but now we don't need to do that we can do that in one line with this swap now as I said there's actually much more complex things I can do so for example I can do something like asterisk X and then I can actually remove this and then have Zed when I do asteris X this means collect all of the values up to but not including Zed so I'm going to grab 10 20 and then 30 will be associated with zed there's a lot of things you can do using the asteris you can use underscores in place of variables if you don't care about what they are so if we didn't want to access y we could do x uh comma uncore then comma Zed and again I've made entire videos on my channel breaking down these Concepts more in depth but I want to leave it there just to give you a brief introduction so with that said if you guys enjoyed this video make sure to leave a like subscribe to the channel and I will see you in the next one [Music]
2024-12-21 15:09