Decorators - Advanced Python Tutorial #2

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] what is going on guys welcome back to the python tutorial series for advanced programmers in today's video we're going to talk about decorators so let's get right into it all right so the basic idea behind decorators is that they add a certain functionality to a function or they surround the function they wrap the function with an additional functionality and i'm going to show you that by using uh just a function in a function first and then i'm going to show you how it's actually done in python so let's say we have a function which is called i don't know my decorator and this my decorator function is used to decorate other functions so what we do is we pass a function we say my deck creator we give to that function another function and then inside of that decorator we specify a so-called wrapper function so we have this wrapper function here and what this function does is it has some functionality and then it calls the function so let's say here we're just going to print a message like i am decorating your function like that and then what we're going to do is we're going to call the function now the interesting part here is now we're not just executing this we're actually returning the raptor function so as a result of that we're not just calling the decorator and passing the function and then we have the decorated output we're actually passing we're actually returning another function that calls the initial function but with decorated code with additional code so how would we do that we would essentially say let's say we have something like hello world here and we just print hello world like that uh now this helloworld function wanna decorate it so what we can do here is we can say my decorator uh and we can pass hello world without calling it we're just passing it as a reference and what we get here when we execute that function is a return value now of course we can save that return value first into a function or something but we can also directly call it if we want to like that so essentially what we're doing here is we're we're calling this my decorator we're passing the hello world function and what we get as a result is the wrapper function that has the additional functionality and also is executing the initial function and then we call this function that we get as a return value so what we're going to do now is we're going to execute this by just saying python main p1 you can see i am decorating your function hello world now of course we can also swap these positions here by just saying uh we're going to have the function first and then we're going to still decorate it this is also possibility so in this case uh we would have hello world first and then i'm decorating the function so there's also a possibility this is the basic idea behind decorators but this is not how it's done in python now when i say this is not how you do it in python i don't mean the whole thing here i mean this particular line of code we're not calling the function passing the function and then calling the result there's a more elegant way in python and this is just using annotations so we can actually delete this line here and on top of this function i can just say at my decorator so by doing that i'm decorating hello world with the function of my decorator so this structure here is the same but now instead of passing it and calling it or calling the wrapper result we're just saying okay add my decorator and then we can actually call hello world itself and it's already decorated so this is enough as you can see oh sorry as you can see we're already uh getting the hint that this is the actual wrapper function so if i run this right now we get the same results so we see hello world i'm decorating a function again we can also change this um by swapping the order and you can see that the order is swapped so this is the exact same thing but we have some limitations here now they're not real limitations because we can easily fix them but right now the way we have it right now uh it doesn't work perfectly for example if i have some parameters here it doesn't work because the wrapper doesn't have the same parameters so um if i have hello world or let's let's just say hello uh i don't know person we need to say hello to a specific person and what we want to do is want to say hello and then the person's name like that a very simple function still uh but we cannot just decorate it like that because the wrapper here doesn't have that function so if i say hello mic and i'm trying to execute this right now you're going to see that we get a type error because that rapper doesn't take positional arguments but we give one to it because hello takes arguments but uh the decorator the wrapper function here does not take arguments now we could easily fix that by just adding an argument here but the point is that a decorator is not necessarily just for one function if i have a decorator that decor that decorates multiple uh different functions we don't want it to be limited to one specific signature we don't just want to say this decorator is specifically for the function hello because then i could just add the code of the decorator to the function hello we want this decorator to be universally applicable and because of that we have to add the arcs and quarkx keywords here so arguments and keyword arguments i mean we don't need to add the keyword arguments necessarily but if you do it like that you're on the safe side because whatever we pass here we can also pass here by simply passing exactly that so this is a safe a safe thing here because obviously if i pass any arguments by by doing that by calling the function here mike i'm passing it to the arguments and i'm passing the exact same arguments to the function so essentially i'm just passing it right to hello again so it's it's not a big deal and if i do it like that you're going to see that it's going to work i say hello mic however we now have another problem let's say it's not print but it's return i want to return a string if i want to return a string here i say return i'm not going to return it by just calling i need to get the return value from the wrapper as well and what we need to do here essentially to make this work is we need to return the value of the wrapper so we need to say um actually we need to just say come on return return function so we can just return the function and then it's the same thing but we're going to see that this has another problem here as well uh let's just see first of all if it works um i mean we would probably have to print the result then print there you go i am decorating your function hello mike so it works but what if i want to have that print afterwards so if i want to have it like that if i want to first return the value or first execute the function i'm not going to first return the value that's not possible but if i first want to execute a function and then want to print or do the wrapper stuff it doesn't have to be a print it can be whatever you want it to be but i want to execute the decorating functionality afterwards after the function call but i still want to have the return value i cannot do it like that what i need to do then is i need to execute the the function call i need to store it in a variable so for example return value is going to be whatever the function returns to us and then we're going to say return after we did the code return the return value like that and then it would also work like that and uh actually did it work the way you want it to work i'm not sure because actually we would want to have hello mic first oh obviously that's not possible in this particular case because we're returning and we're printing down here uh but if i would have something like print and return so if it would have something like print uh the same string hello mike actually not my person if we would do it like that we would see a difference here because if i do it now we get hello mike i'm decorating a function hello mic and if i'm not doing it like that if i'm directly returning or if i'm if i'm doing it like that i'm going to first get i'm decorating your function dense two times hello mic [Applause] as you can see now let's go ahead and look at two very simple uh practical applications because up until now this was quite abstract so let's actually go ahead and delete all of this and now what we're going to do is we're going to have the first practical example practical example number one is going to be logging now this is not how you would actually do logging in python in the intermediate tutorial series we already talked about the logging module and so on but for the sake of simplicity i'm just going to open up a file and write to it in a very uh in a very simple way i'm not going to use the logging module here um but we're going to see why maybe using decorators here might be a little bit more comfortable than actually logging every time in a manual manner so let's say we have this function or decorator locked we're just going to call it locked we add a function or pass a function to it and what we do then is we have the wrapper function def wrapper and we pass arguments and keyword arguments so that it's definitely working and then what we're going to do is we're going to say value or return value whatever it's just the function called on the arguments on the keyword arguments so that it's compatible with all different types of functions and now we can decorate actually so now we can go ahead and log whatever is happening and we can do this by saying with open log file dot txt in appending plus as f and what i'm going to do here is i'm just going to say let's first of all get some some values here so let's say fname equals function dot underscore underscore name underscore underscore and this would give us the function name and then we can say f dot write and we can formulate an f string here we can say function name uh returned value value like that and of course we can also use the same thing to print this so we don't need to necessarily uh to necessarily just write it into the file we can also say print and we can print the same thing here like that so what we do after that of course is in case there's a return value we're going to return it otherwise we're going to just return none or anything like that uh and then we're going to say return the wrapper here and we're done with the deck creator and now i can have a very simple function here uh first of all do i have any errors here no i don't have any errors so let's say we have a function add and we have just x and y here and what we're doing is we're just returning x plus y a very simple function here uh and now i can first of all show you what happens without decorators so we're just going to say print at 10 plus 20 in a very simple way here so first of all we have an invalid syntax oh obviously because we have one star for the arcs and two for the keyword arcs so this should work yeah there you go you get 30 as a result and now we're going to add the locked decorator here so we're going to say add locked and we're going to see that there is a difference here and you can see add return value 30 and we should also be able to see it here so let's open this in split mode here and you can see at return value 30 and of course if i go ahead now and execute this again and again and again and again um probably we need to close this and open this up again but you can see oh maybe we should add maybe we should add a new line here as well so we should say backslash and in the end so that we always log in a new line and you can do whatever you want you can also use the actual logging module you can use the timestamp and so on but this is one practical example of why decorators might might be useful so let us look at a second example here and this example is going to be timing so let's say you have a function you want to know how long it took to execute so we're going to have the second practical example your practical example 2 is going to be timing functions so for this we're going to import time and we're going to have the decorator called time uh timed like that i'm going to pass a function here we're going to have the wrapper here and this wrapper what it's going to do again it's going to take uh arguments we're going to take keyword arguments and uh we're going to basically do the same thing but before we do anything we're going to have the first time stamp so we're going to say okay before equals time dot time so we're getting getting the the current time right now and then we're starting with the whole execution so we say value equals um function on the arcs and keyword arcs like that and then we say after equals time of time so what we're doing is the whole function call the actual function call of the past function is happening in this particular line and before that line and after that line we have a timestamp so we can now go ahead and calculate the difference so we can say okay print uh oh i don't know let's say actually we can get the file name as well here so let's say fname equals oh not finally function name sorry function dot underscore underscore name and we can say i don't know fname took and now we say just after minus before seconds to execute like that and we can now go ahead and do i don't know what we can just define a random function my function here and the only thing this function is going to do it's going to have a result starting at one and then we're going to say for x or actually not x maybe let's see for i in range uh x uh we're going to say result times equals i it's a very simple thing and then we can return that result return result and the basic idea here is that we just want to have something that takes uh takes the time takes some time to be calculated uh do i have a problem there oh yeah i need to return the wrapper i'm not sure if that's the problem though yeah seems to be the problem um and then what i'm doing here is i'm just saying oh and we need the value as well actually we don't need the value we can just call the function here so i can i guess i can get rid of that um yeah like that so we can just call the function here in this case unless we're returning something actually maybe we should return it though yeah that's that's let's do a return here so let's say value equals that and then after the print we're just going to return the value like that um and then we're going to add the tag here but first of all again let's just see what happens if we just say print my function uh ten thousand let's go for a hundred thousand let's see if this kind of works here we get zero why do we get zero we have oh because we start at zero that's not good let's do it like that and it takes some time maybe takes too much time so let's go with one less zero here and you can get a result here so if i now go ahead and time this we're going to get a timing as well so we're going to get timed here and uh i think the message somewhere up there maybe we should not print it maybe we should just execute it without the print so let's get rid of that and let's get rid of that so that we only see the execution time you can see it took 0.025 seconds now if i change this to a 9 here maybe it's going to take longer so um hopefully not too long yeah there you go 5.6 seconds to execute so this is one other practical example you could just go ahead and have this time decorator whenever you know whenever you want to know how fast the function executes and maybe some other values as well you can just add at times above it and then you have the execution time so that's it for this we hope you enjoyed i hope you learned something if so let me know by hitting the like button and leaving a comment in the comment section down below and of course don't forget to subscribe to this channel and hit the notification bell to not miss a single future video for free other than that thank you very much for watching see you next video and bye [Music] you
Info
Channel: NeuralNine
Views: 10,290
Rating: 4.9682541 out of 5
Keywords: python, programming, advanced, tutorial, coding, professional, expert, level, software engineering, python expert, python advanced tutorial, python advanced, object-oriented, intermediate, decorator, decorators, annotation, annotations, wrapper, wrappers
Id: iZZtEJjQLjQ
Channel Id: undefined
Length: 17min 50sec (1070 seconds)
Published: Sun Jan 31 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.