5 Awful Python Mistakes To Avoid

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
this video was brought to you by IND dentle IO learning python Made Simple how's it going everyone in today's video we're going to be covering what I believe to be my five worst mistakes in Python and these are mistakes that I've made throughout the years or actually when I started programming in Python I was quite naive so hopefully by bringing these up you can avoid the mistakes that I made in the past starting with the very first mistake I made and that is to perform unreliable or bad benchmarks because in Python there are going to be moments where you want to test whether certain functionality is faster than other functionality but what I learned a bit later was that timing your code is not as simple as it looks and I'm just going to paste in an example and I'm going to explain more as we go through this example so here I have two functions that I want to test for and what I'm testing for is whether pass is faster or the ellipses is faster and this is just a hypothetical test I don't really recommend you care about whether pass is faster than the ellipses or vice versa but in this example we're going to pretend that we care about that then I'm going to create a function that can time these functions so here we have a function called get time which takes a cable and then we have a start time which uses the performance counter from time then we run that function and call that once again so that we can subtract the end time from from the start time and at the end it's going to say that the function name took this amount of seconds so here we're testing how long a function takes to run once then below that we can create our if name is equal to Main Check and try to run these functions so first I'm going to typing get time for the ellipses and since we're calling it inside the get time function we should not call the function here and then we're going to try it with the pass statement now if we were to run this you'll see that the ellipse took longer in this case and if we were to run it again the ellipses still takes longer this can make it very easy to come to the conclusion that the ellipses is slower than the P statement but once again as I mentioned there are a lot of factors that come into play when you are trying to time your code for example what's happening in the background of your computer can also affect the speed of a test also watch what happens when I change the order of this so now we have the P statement above the ellipses all of a sudden the tests look a bit different now the pass statement takes longer than the ellipses and once again that's because this was just not a reliable way to time our code one thing that we can do to stabilize the results is adding a warm up and a lot of you claimed from the last video that you don't really need to warm up your interpreter I can't really contribute too much to that discussion but as soon as I add a warm-up statement or some warm-up code the tests become much more consistent the first one of course takes the longest it's the first code to run in the script but then the second two just start to normalize and they get closer and closer or that's not always true but they are quite close so in most cases I will always provide a warmup because on my computer it does something but there was something else we did incredibly wrong here and and that is performing our test only once if you have a function that lasts very long or that takes very long this might be okay but if you're looking for those kind of micro optimizations or not really micro but functions that take milliseconds you're going to want to use something better such as a profiler or the time it module because these give you much better tools for actually timing your code so just to sum it up timing code in Python is not always as straightforward as it looks because it's such a high level language it makes it just much more difficult to understand what's going on underneath all of this functionality my biggest recommendation is to always have people double check your benchmarks or even post it on stack Overflow where you can get roasted about your benchmarks I would treat it as a scientific journal so document it have other people try to reproduce the results and if a lot of people can reproduce the results then you've got a good bench Mark but otherwise it's very easy to create biased tests such as this one so be careful moving on to my second biggest mistake in Python and this has to do with early optimizations when you first start programming you get this idea into your head that everything has to be perfect from when you start writing your code and while that's the ideal scenario what I learned is that sometimes it's better to create code that gets the job done rather than code that performs at the speed of light when it doesn't even matter that it performs at the speed of light because the difference between 20 milliseconds and 18 milliseconds might not even matter in that context anyway suppose you're creating a program and you need to check for a user's age if you're new to programming you might end up writing code like this and this code is perfectly fine in the sense that it does exactly what you needed to do so I wouldn't worry about this immediately I would continue working on making sure that the program can actually function and then with experience you might be able to change this with a much easier implementation which obviously is just returning if the age is more than equal to 21 rather than returning true or false which is always considered to be a noob move but regardless of how silly this looks I would still continue working on the rest of the program before trying to fix it and I probably wouldn't even care about timing this because learning simple tricks like this just comes with practice for me it's quite obvious that I should have done this from the start but but in this simple example it might not have been so obvious for a lot of people but now I'm going to show you a much better example of optimizing your code or prematurely optimizing your code so in this example we have a function that calculates the sum up until n and the way we're going to do it is first by creating a variable called result then for I in range n we're going to add I to the result each time so we're gradually adding those numbers together and then we're going to return the result in this case this was the most readable and most straightforward approach to creating this function and if we wanted to test it out you'll see that it works just fine if we're calculating the sum of 10 we're going to get 45 back but while this was incredibly straightforward it is not the optimized approach and if you insert a huge number this can take ages to calculate but once again it gets the job done and supposing that we're not ever going to insert those huge numbers it's probably just fine later on in our program if we decide that it's too slow we can always go back and optimize it using the arithmetic series formula so this is going to perform the exact same operation as this or it's going to give us the same result at least and we can verify that by printing calculate sum optimized and passing in 10 what we should get back is 45 and as you could see if we inserted a number such as 10 we get the result back instantly and that's fine for for both of these cases but now I'm going to bring in my get time function except this time I also decided to include arguments because we need to pass in some arguments to our function and we're going to time both of these functions so first I'm going to start with our if name is equal to main check and then I'm going to get the time for the calculate sum and I'm going to pass in 10 and I'll do the same thing for calculate sum optimized and if we were to run this they're both going to give us back 0 seconds because they are both very fast with small numbers but now watch what happens when I insert 1 million you'll notice that the original implementation took significantly longer it was instant but not as instant as calculate sum optimized and even worse if we were to change this to 10 million you'll start to see the effects of how slow or actually it wasn't that slow with 10 million so we're going to change that to 100 million and now it starts to delay the original one took 3 seconds with a huge number such as 100 million while the optimized version still took no time and if we were to comment that out you'll see that this one is instant while the non-optimized version took 3 seconds so all I wanted to say here is that sure it might be cool to optimize your code from the get-go but in many cases it's going to be much better to have a program that actually works rather than wasting hours is to optimize your code so it works at Peak Performance and how fast you want a function to actually work always depends on your use case if you're running a script once a day you might be fine with waiting 3 seconds otherwise if you're running your script thousands of times per day eventually you might want to optimize those Snippets of code or also if you know that the number is going to exceed let's say 100,000 at a certain point you're going to understand that the original implementation just doesn't suffice so so you can optimize it but doing it from day one can really ruin your productivity up next we have the third biggest mistake that I've made in Python and this goes back to when I first started using python several years ago I wrote all of my code without type annotations because I just came from java and Swift and I was incredibly happy that I could finally ignore those things but after coding for a while I realized that I make a lot of mistakes I am human and I recognize that when I'm tired or when I'm not paying attention I'm going to make a silly mistake which can be really tough to catch later so about a year ago or maybe two years ago I decided that I'm always going to annotate all my code even if it's a simple data type it still saves me the trouble from making silly mistakes for example you might have a name of type string which is obviously Bob and then you might have an age of type integer which in this case we're going to set to 100 now if you have a static type Checker or a modern code editor you're probably going to see some squiggly lines that tell you that you're assigning the wrong data type to the variable and if we hover over it you'll see my piie will even complain that we expected an integer but we got a string instead and that's really good because when I'm tired this might have accidentally happened I know it looks quite silly that it could happen with a basic data type such as an integer but it does happen and without this type annotation I would look at this and I would think yeah it looks about right to me I mean when you're tired you do not see these things so we get no warning from the editor that we did something that we did not want to do age is inferred as a string python works just fine nothing's going to crash here and then later on in our program we'll use that age as if it was an integer and it might or might not work but I much prefer the certainty of knowing exactly what I'm doing so I'm going to change that to integer and and then we can just pass in Bob's AG which is obviously 1,29 and type annotations also help with context actions which can also make it much easier to develop code but just a quick disclaimer if you are editing your code in notepad or in Vim without additional plugins you're probably not going to get any of the benefits of type annotations but I haven't tried to use Vim or notpad to code so do let me know if you would use type annotations there or not or whether it's completely useless but in modern code editors it brings you a lot of benefits or I actually take that back because with notepad or Vim you can run a static type Checker to check whether all your types are what they should be but I really like when I see squiggly lines in my project or I don't really like it but I'm happy that it does warn me anyway going back to the function here we're going to create one that says fire employ and that's going to take a name of typ string and it will return none because we are just executing code here now if we were to type in print the FST string of name. capitalize you'll see that we're going to get the context actions for a string without this string type annotation Python's going to have no idea what name could be or that's not completely accurate our code editor is going to have a hard time inferring what name actually is because we have no information regarding it here so we're not going to get those context actions so here I'm going to say that it's Tye of type string and we're going to capitalize name in case it's not capitalized and of course we're going to type in you areed now I'm going to create my if name is equal to Main Check take these Global variables and put them inside our main block and just like that we can now use our fire employee function and it's going to safeguard or it's going to warn us if we put in a data type that we should not such as let's say I don't know uh we can pass in 100 here we're going to get those squiggly lines or if you run my Pi it's also going to give you some more details regarding this error otherwise if we were to fire an employee called Bob and we can just actually pass a name here this will work just fine because it's of the correct type it's of type string and this is going to crash the program so I'll remove that but now if we were to run this you'll see that Bob you are fired otherwise if we were to pass in that incorrect type of integer our program is not going to be able to process that because int has no attribute capitalize which is the first operation we perform in our function so obviously this is not going to work and getting a warning that that's not going to work is lovely although I did notice that recently in pycharm it looks like they had an update which still warns us even if we do not pass in the data type so here it says type int doesn't have that expected attribute which is quite cool I I think it's cool that that py charm can infer that by seeing how it was used within the function but before we wouldn't even get a warning here because name has no information which means we can literally pass in any data type we want and that would be acceptable so defining it to be of type string is just much more specific and self doents the function a little bit but type annotations get much more complex than this and if you're curious about the benefits of type annotations and how to use them much more professionally I have a full course on this which you can find on my website I'm going to leave a link to it in the description box down below just in case you're curious moving on to my fourth biggest mistake and in this example I created a module for Bob which is called Bob's module and inside Bob's module we have a few functions one is called get description which returns a description of Bob's module and the next one's called get name which Returns the name of Bob and we also have a function which returns to us a random Bob and here I have four options that we can return and I use random. choice to pick a random option and obviously while I'm developing this script or this module I want to test the functionality so down at the bottom I would print all of these and if we were to run this you'll see that all of it works just fine we get Bob's name when we use get name we get the description when we use the description and we get a random bul which changes each time we run the script so next I'm going to go to Main and I'm going to import Bob's module as Bob and then we can paste in all that functionality we have random Bob get description and get name and if we were to run this what you should notice is an output such as this one otherwise we can also print something else like hello world and you'll see that that doesn't work and this is one of the biggest mistakes I still make today and that is running the wrong script and no matter how many times I changed this it's not going to affect this because obviously I'm still running Bob's module and in a very short moment I'm going to show you my solution to not making this mistake anymore but just for now let's pretend we remembered that we need to change the script right click on Main and run main now we have the second problem we have a double output and that's because when we import Bob's module we actually run all of the code inside Bob's module which means our test at the bottom also got run so a very important addition I always use in all of my scripts is the main entry point and the main entry point is actually quite optional it's good for encapsulating your code and excluding it from the global scope but what's really important for your scripts is the if name is equal to main because this will check that we're running the script directly before executing this functionality so if we were to copy and paste this inside Main and go back to our main file you'll see that we will only get the output from within main.py because Bob's module was not run directly if we were to run Bob's module directly this time it will run the code from within here and to make that more obvious I'm going to also print Bob's module at the top and as you can see we get Bob's module executed but another great benefit of doing this is that in most modern code editors you get this green play Arrow next to the script or in the script that you're currently looking at so instead of in of using the shortcut one thing I'll usually do is tap on this green arrow just to ensure I'm actually running the correct script and if we go to main.py we can do the exact same thing we can create our if name is equal to Main Check and paste in the code that we want to run now if you're using py Cham you're probably not going to have this shortcut if you type in main you're only going to get the if name is equal to Main Check the reason I get also this main block here is because I went into a setting called live templates and I created my own live template which means that I also get this shortcut when I type in main anyway now that we have all of this we can tap on that Green Arrow and that's going to ensure that we're actually running the correct script and that's why I always highly encourage you to use if name is equal to main it helps prevent random code from being executed from other modules because once again as soon as you import a module all of this gets run and if you're testing anything you obviously do not want that test to get executed while you're importing it into a real project otherwise an added benefit is that you get this silly green arrow that allows you to make sure that you're running the correct script and finally the last mistake I always make and this is mostly due to being just lazy is not planning out my projects before I actually try to build them when you want to create a website or some sort of product in general you will create a sketch that contains what you want your project or your product to look like and in general this is a great idea because it saves you a lot of time and effort when it comes to figuring out what you actually need to do to make this program or product function so if you have a piece of paper I absolutely recommend that you try to plan your project before you actually write the code or if you don't have pen and paper of course you can also try to plan it inside a script for example in imagine we're creating a lamp or a smart lamp so here I have a class called smart lamp and right now the only thing I did here is create an initializer that takes a name and a version and obviously it might make sense to type in all the functionality as we create it but a better alternative is to actually just create that blueprint here I created all of the possible options that a lamp should have such as being able to turn itself on or turn itself off or to check for updates but I did not Implement any of that code I just created this blueprint for what my smart lamp should look like so I wouldn't forget later what I would have to include when writing the code this makes it much easier to plan how our lamp should look like which in turn is going to make it much faster to program and obviously this is a very simple class there's only three functions or three methods that we need to make this lamp work so for much bigger projects this can be even more beneficial because there's nothing worse than forgetting a very important piece of functionality for your project and again this can save you from a lot of trouble because now you know exactly what the end product should look like meaning that once you have all of this you can just start typing the code without having to think what's missing now obviously this isn't foolproof so you are going to probably miss some functionality here and there because errors do arise unexpected functionality does come up that's just how things are and you'll get used to it but having a blueprint of what you should be making just makes the development process much more smooth but yeah obviously I don't do this all of the time because I'm a very very silly guy but I really should and yeah that just about concludes the five biggest mistakes that I make in Python most of these are very straightforward and don't really take that much time to learn but as always I would really love to hear what your mistakes were when you were learning python or which mistakes you recently came across that you wish you learned earlier or which you're very happy you learned about recently and um yeah with all that being said as always thanks for watching and I'll see you in the next video
Info
Channel: Indently
Views: 24,115
Rating: undefined out of 5
Keywords: pyton, pyhton, pythn
Id: 8CM1UMV-tNQ
Channel Id: undefined
Length: 22min 13sec (1333 seconds)
Published: Wed Jun 05 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.