Python's 5 Worst Features

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 Python's five worst features and it's very important to stress that this is highly opinionated and based off of a lot of the code that I saw on the Internet or for my students starting off with the first worst feature and this is called implicit string concatenation and the way it works is by creating a string such as text and creating another string directly after that we can type in text 2 for example in Python when you have two string literals next to each other it implicitly concatenates them which means in other words this is similar to this and we can verify that by printing our text as you can see when we print it inside the console we're going to get both the strings concatenated and this also means that you can create some more complex strings using implicit string concatenation of course it gets a bit complicated to find out which quote is opening and which quote is closing if you use a lot of these but otherwise it works just fine but usually you won't see it being used in such small strings it's much more common to see them being used in larger strings such as this one as you can see this is some very long text and we don't have a comma here or a plus here all we have to do is tap on enter and it's going to create a new line and at the end of this when we print this it's going to print nothing because we didn't print anything but if we do print this we're going to get this very long line although this approach did require the parenthesis and if you don't feel like using parenthesis you can also use a backslash such as this one over here and this will trigger line continuation so still we do not need to use a plus to concatenate these long strings and there it uses this implicit string concatenation so you might be asking why does this feature suck in some scenarios this can lead to some very buggy Behavior such as here I decided to create a list of names and this list of names is going to be a list of type string so what we have here is Bob James Bob 2 Ashley and George and we can consider this to be five names but as soon as we print the length of these names what we're going to get back is three and that's because we made a very primitive mistake and that is to forget to add the comma to the next two elements but thanks to implicit concatenation we do not get any errors so that completely slips us and to show you what I mean if we were to print these names you'll see that the last three names will have been concatenated into one element and that's quite silly because it's a very honest mistake that's easy to make especially if you're writing things on a single line such as letters of type list of string and you were to type in a b c d e sometimes we make these mistakes it's very easy to forget a comma and once again as soon as we print these letters what we're going to get back are these three strings even though we thought we created Five so in my opinion that's just a very poorly thought out feature in Python because it's not really that explicit and in my cas case I tend to make this silly mistake many times so it just ends up becoming annoying moving on to the second worst feature and for this example I'm going to create a list of names James Mandy Bob and Martin and as usual I'm going to Loop through these names so for name in names if name is equal to Bob we're going to print that Bob is breaking stuff and the party will be over then we will break out of the loop because if there's no party there's no point in continuing with our for Loop otherwise if Bob didn't break anything we can continue to party so there we have a very silly for Loop and one thing you might have learned recently in Python is that you can also specify an else Block in for Loops while loops and try and except blocks and the else block only runs if everything is executed successfully in the for Loop or if all the iterations happen so if Bob doesn't break anything this block will be executed right now if we were to run this we would get that the party is over and the else block will not get executed because Bob is breaking stuff once again but in the case that Bob does not break anything you'll see that the else Clause will get executed because we were able to iterate through everything properly without breaking out of the for Loop so James is partying Mand is partying Bob is partying Martin is parting everyone is parting and as I mentioned the else block also works with while Loops so here we have a simple while loop that checks that I is more than zero and if it is we're going to print I but if I is equal to one we're going to break out of this Loop and one thing that's very important to remember is to decrement I on each iteration so we don't get an infinite Loop now at any moment if we were to break out of the while loop the else block will consider it to be a failure so it will not get executed but if this naturally returns false then the else block will be executed because the while loop ended naturally in that case but right now if we were to run this we would not get that else block executed because we included a break statement but if we were to remove that the else block will get executed because the while loop ended naturally this expression here evaluated to false naturally there was no bre break in our while loop and finally as I mentioned you can also do this with try and accept for example here we're trying to run some dangerous code and I have an exception here which I commented out so I can show you both cases where we have an exception and where we don't have an exception then directly below I handle that Exception by printing I handle the dangerous code and obviously I don't recommend you handle exceptions like this because it's just not specific please be specific with your exceptions if you're handling a value error handle that value error specifically exception is just far too broad and tells anybody that's reading your code that whoever wrote this just doesn't care or just couldn't be bothered to write proper code anyway once again we have this else block and all the else block does here is run if there were no problems or errors in the tri block so if all the code ran successfully the else block will be triggered once again again in this case if we were to run the code it will get triggered because there were no errors congrats otherwise if we were to raise an exception or if we were to encounter an exception naturally the else block would not get executed because something went wrong in our Tri block anyway now that you understand what the else block does the reason it's such a terrible feature isn't because of the functionality itself but it's more due to its name it is unintuitive and it's hard to read there's not a single developer in the world I'm ready to bet I mean of course that's my opinion that can read this at a first glance without having had read the docs of python extensively it really requires you to associate another word to it to understand how it works in my case I always refer to it as the success block and the reason I refer to it as the success block or actually the success listener is because the else block only gets executed if all of our code runs successfully whether that's in a while loop a for Loop or a try and except block if our code runs successfully without any errors without any breaks this block will be executed otherwise if I were to leave it as else I would never remember what this was moving on to the third terrible feature star Imports and it's not really a terrible feature in itself it's just that a lot of people mess up their code by not understanding what it actually does and for this example I actually created two extra modules to demonstrate the dangers of star import one is called utility which is a module with some random functions such as ADD call Bob and random and this unused import time statement doesn't really matter so I'll remove that and I also created my very own maths module which also has an ad function but I made sure to state that this one comes from the maths module while the one in utility comes from the utility module but let's let go back to our main.py file and here we're going to type from utility import everything and also from math import everything now the very first thing I'm going to do is add one two and three and I'm also going to call Bob these are two functions that we absolutely want to use in our script and if we were to run this you'll see that the code will work just fine I mean Bob doesn't respond because he's always busy but otherwise we were able to add 1 two 3 from mats and we were able to call Bob so what was the problem here well the problem here is that we accidentally shadowed some very important functionality from the utility module and what that means is that we made the awful mistake of making import order matter because right now we're using add one23 from the maths module but if we were to move this line up you'll see that the next time we run this it's going to be the one from the utility module and this is something you never want in your script because it can be incredibly hard to debug and that's why the star Import in general is considered to be an awful practice because it can potentially Shadow a lot of functionality that you have in your script meaning that you might get some very undefined Behavior which is really hard to debug but let's reverse that and let's take it a step further by importing everything from random so I'm going to just remove Co Bob and I'm going to print that the random integer of 1 to 10 is equal to whatever it gives us back and then I'm also just going to call random if you're using a powerful code editor you might be able to understand from the context which random you are actually using here it says we're using the one from utility but let's see what happens so if we were to run this you'll see that we will only get two print statements back but random is not going to give us any anything back even if the docs told us we were using the one from utility and just to show you what I have in utility is a random function that says Bob is dancing on the table question mark so our code editor told us that we would be using this one but instead what happened is that we used the last one that was imported which of course is the one from random so if we were to print random we would get something back such as this very crazy decimal but the point is we expected to use the one from utility and once again that's because import order matters now which means we need to move random All the Way to the Top If we want to use the one from utility and this time we'll get back that Bob is dancing on the table so yeah in my opinion this is another pretty terrible feature if you don't handle it properly I would love if the code editors were strong enough to tell us that hey you're importing everything and this actually collides with something such as random I really wish there was a warning somewhere here that told us that we had some very serious name shadowing going on moving on to Python's fourth worst feature and this one is called mutable defaults so to show you how it works I'm going to create this function and I've called it add name and what it does is take a name and add it to a Target list but if we do not specify a list we want to create a new empty list for our name now most code editors are going to warn you immediately that you're providing a mutable default and the reason they're warning you about this is because in general you don't want this it's going to create some very buggy Behavior later on in your program but anyway we're going to ignore that and we're going to provide that mutable default and it's also Worth to mention that this could also be a dictionary the concept Remains the Same here but we're going to be using a list in this example next we are appending to the Target the name that we have provided and what we want to do is return the target so next Let's test out our function by printing it three times and the first time we're going to print that we're adding the name of Bob then James and then Maria theoretically each one of these should give us back a list of one element but instead what's going to happen is that we're going to refer to the same list over and over and over over because this was evaluated once during the execution of the script so in theory we just created a variable called Target and stored it so each time we added a name without specifying a list it was added to the Target variable if we were to specify a Target at any point then it would not have that behavior but as soon as it referred to the default mutable argument it used the one that was created in the function so that's just another terrible feature that python has and I know it has to do with its implementation it's hard to change the implementation of an entire language but it still would be nice if we had a better way of creating mutable defaults because right now if you want to create a mutable default you're going to have to change this code up a little bit for example instead of creating a target of list of type string we're going to have to create an optional here so of list of type string or none and initially we have to set this To None next in inside our function we need to type in if the target is none that means that the user did not specify a list to add the name to so what we're going to have to do is create a new list and below that we can type in target. append and we can append that name now if we were to run our code we would get a new list created each time we added an element without specifying a list because now it's explicitly checking whether the default argument for Target is none and if it is it will create a new Target on the spot but yeah that's just some boiler plate code I wish we didn't have to do it's not the end of the world of course but it's quite annoying and finally it's time for Python's fifth worst feature and this has to do with creating copies of data or to be more specific copies of lists and iterables so for this example I'm going to create a list which can literally hold anything so that's going to be of type any and what the list will contain is first the integer value of one and then a nested list of strings and then it's going to hold the integer value of two and I know this is a very lazy way of annotating this type I just really did not want to type in list of integer or list of type string I thought it would be overkill for this video so I just left it at any what we want to do next is create a copy of this list so what we're going to do next is create a variable called a copy which will be a list of type any because it's literally just a copy and that's going to equal a do copy and that's great now we have a copy of our list so there we can do whatever we want with it without affecting the original but what I'm going to do next is modify this element here in the copy so I'm going to refer to a copy and say say at the index of one which is this index here and what we want to do inside here is refer to zero and that will refer to a and what we're going to say is that this will now be equal to X and with that being done we're going to print both of these lists so the original and the copy and what's going to happen is that both of them are going to have been modified even if we only referred to the copy and if you've been programming in python or any programming language for a long time you will know that this is because we created a shallow copy and that the list inside the shallow copy has its very own reference which is quite unintuitive for new programmers and also the name of copy can be quite unintuitive in itself I mean if I copy something I want to have a copy of it not a shallow copy so personally I think it would have been very nice to have something more explicit such as shallow copy when you are creating a shallow copy but in this case copy does just that it creates a shallow copy but the solution for this is actually quite simple and all we need to do is import from copy the Deep copy and instead of copying a we can deep copy a and this time it's going to only modify the copy which is exactly what we wanted in the first place but now you might be asking why isn't deep copy the default well deep copy is much more memory intensive since it copies absolutely everything it performs this deep copy wow I'm really having a hard time speaking it creates a deep copy of every single element so in many cases it might make more sense to return a shallow copy because it's faster and more memory efficient than creating a deep copy and from what I understand that's why it's the default personally I just hate that it's something you need to memorize it's not very explicit unless you read the docs but if you've been programming for a long time you would probably expect a shallow copy to be returned from the start but yeah that just about covers everything I wanted to talk about in today's video once again this is heavily opinionated so it's nothing to refer to as a fact to anybody of course you can refer people to this video if you want to talk about Python's worst features but it's nothing scientifical and there aren't really any docs that support the claims I'm making it's just my opinion and python is still my favorite language of all time so even if it has some things that are hard to understand or not written out so well it still helps me do what I want to do in life and the five features I mentioned really just take a couple of minutes of studying or of reading the docs to understand how they work so that you can either avoid them or use them with caution but with all that being said I would love to hear what you consider to be the worst features in python in the comment section down below I'm sure I missed a lot of terrible features that python actually has but these are the first ones that came to mind when I started creating this video so yeah with all that being said as always thanks for watching and I'll see you in the next video
Info
Channel: Indently
Views: 82,367
Rating: undefined out of 5
Keywords: pyton, pyhton, pythn
Id: j6WuHCSwNDo
Channel Id: undefined
Length: 19min 44sec (1184 seconds)
Published: Thu Apr 25 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.