We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Python Decorators: Gift or Poison?

00:00

Formal Metadata

Title
Python Decorators: Gift or Poison?
Title of Series
Number of Parts
132
Author
License
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
Why would you ever need to use decorators in Python? Have you ever had the task when you need to use one function in few places and you really wanted to avoid of code duplicating? For example to add some logging into functions or timers, etc. Decorators in Python are super powerful with these tasks, but at the same time they are super complicated, sometimes even magical. When I started learning Python, Decorators were really like a magic: how to use them, how are they working, lots of questions. The goal is to make the things easier and clear to answer a question: to use or not to use Decorators in your project. What’s in the Talk: - Functions nature in Python - Magic of a Decorator - Basics - When to use Decorators - Examples - Even more Python magic
Presentation of a groupSlide ruleCodeCuboidMultiplication signSlide rulePresentation of a groupDigital photographyWordCodeInformation securityTerm (mathematics)Thread (computing)InternetworkingComputer virusHidden Markov modelDampingBuildingVideoconferencingNP-hardSoftware bugComputer animation
Function (mathematics)Object (grammar)Software developerFunctional programmingNatural numberSocial classVideo gameObject (grammar)Functional programmingComputer virusPhysical system2 (number)Open sourceNormal (geometry)Type theoryEmailService (economics)Thread (computing)Computer animation
AdditionType theoryFunction (mathematics)Object (grammar)Graph coloringParameter (computer programming)Social classType theoryFunctional programming
Function (mathematics)Object (grammar)Inheritance (object-oriented programming)Functional programmingType theoryParameter (computer programming)Computer animation
Function (mathematics)Functional programmingParameter (computer programming)2 (number)Row (database)
Social classFunctional programmingMultiplication signSymbol tableParameter (computer programming)2 (number)Computer animation
Social classFunctional programmingSocial classBitCASE <Informatik>
Social classFunctional programmingSocial classLetterpress printingBitComputer animation
Functional programmingCodeLetterpress printingLine (geometry)ResultantTable (information)BitParameter (computer programming)Function (mathematics)
Function (mathematics)Functional programmingCode
Functional programmingCASE <Informatik>Coefficient of determinationTwin primeComputer animation
Function (mathematics)Social classLogic gateLine (geometry)Lambda calculusSoftware testingCodeKeyboard shortcutRange (statistics)Touch typingSoftware testingFunctional programmingMultiplication signSocial classUnit testingKeyboard shortcutDistribution (mathematics)Range (statistics)Parameter (computer programming)Line (geometry)Single-precision floating-point formatCASE <Informatik>Boss CorporationDisk read-and-write head2 (number)BitSoftware bugPoint (geometry)Function (mathematics)CodeResultantNumberWritingLambda calculusSoftware developeroutputNetwork topologyWordLetterpress printingGodFerry CorstenMusical ensembleVolume (thermodynamics)Coefficient of determinationComplex (psychology)Computer animation
Transcript: English(auto-generated)
Thank you for coming to my talk. I'm working for a Syrian company in Berlin. You can access presentation slides, they are published online, and also code snippets if you want to check
them later or right now. While doing that, you can make a photo and I will tell you a story, how I started with Python decorators and why I wanted to make this talk happen. Basically, when I started working with Python, it was really unbelievable for
me that I will turn back to Python, turn just to Python, because I was C++ developer, we were working in a team of ten people, we were so excited to start, and then in one week, suddenly, our customer told us, hmm, now you're writing Python. We said, yeah, why not? We would try. It was really nice and funny, and we tried to build something from
scratch, and then we were kind of using decorators, it was a bit hard for us to understand, so we Googled, we found something, and then it was magically working. Somehow, we
didn't go deeply in details, but it was working, it was fine. Sometimes, it was throwing some weird bugs which we couldn't really understand how it is working, so we were just replacing with a normal code. It's fine, it can work, but sometimes you really would like to have a nice decorator which you can use everywhere to just invent your
own wheel, or just to reuse the code. So, a few words about my company. I'm working for an internet security company. It's all about security, and I will show you some
really nice video. So, siren is about security. The internet security is raised against time, and there are only minutes when the virus or some threat is launched,
and then it's trying to block all the users, it's trying to mess up with the payment system and everything, so it depends on the virus type, or the viral email, or something. Sometimes, it's common that, hey, do you know me? And then some of our business
partners answered, yeah, hey, how are you doing? And then, please, I'm stuck somewhere, please pay something. Yeah, yeah, of course, I will give you money. So, that's about siren. We are blocking those kinds of threats. We are fully online, so we have
everything as a service, and then it's just numerous seconds to detect something new, and then to block it. That's why just go with us, if you are the company. I really like the company, because we are pretty open to something new, and then,
as long as the developer has a new idea, something to use, then the company is saying, yes, just go for it, and we are super happy about that, but we are not open source yet. Maybe in the future, we will see. So, what's in the talk? The name of the
talk, and then we will see the answer of it. First, we will think about functions nature in Python, and then I will show you some magic of decorators, then we will dive into basics, and then I will show you some examples, and maybe some examples
from my real life. So, let's start. Functions nature in Python. You know, all the functions are first class objects. What does it mean? That means that you can return function as an object, you can assign function to another object, you
can do whatever you want, the same as you can do with objects. Can you see the code? Yes? Okay. Let's try to run it. Just a second. So, we have just
normal function, it's printing hello something, and then the variable, and we are assigning this function to another function name. And then we are trying to call the function. Let's run it. It's simply printing the same. So, those
two functions are equal. Basically, it's just one function. The function which is say hello, it's an object. And this object was assigned to another name, that means that my function is basically the say hello function. And what
will happen if we will try to delete say hello, it's still working.
Why? Because it's an object. So, we assign the object, and then it's working. Another thing that the name of the function is the same, so if we will print, it will have the same name, because we assign the say hello name, we
didn't delete the function, we just delete the name of it. The name of the
object. Let's go further. Now, as you know, functions are objects. You can dive more into decorators and to understand how they are working. Let's see the magic of it. There are two types of decorators, there are
function decorators and class decorators, and we will basically cover all of them. First, about function decorators, let's build the basic one. It's a decorator which is just printing something, that something happened, it's decorating some function, which is getting as an
argument, it's a decorated function, it's an argument, and then we can use the decorator like this. It's a syntax sugar with at, and then the name
of the decorator, the function which is a decorator, or we can just assign it, it will do exactly the same. So, my decorator is the name of the decorator and my second function is the function which is going
to be decorated. Let's run it. So, what is actually doing? The decorator is also a function which is taking another function
as an argument and also running it, or can just skip the running of the function, but it's definitely changing the behaviour of the function. That means that just be careful when you're using decorators, you have to be sure how the decorator is working, because if it's doing something
super weird, for example, removing the running of the function, it might be wrong, and if you will not dive deeply into the decorator, the decorator itself, then you will not find out what is happening there. So, both of these types of assigning the function into decorators are
working the same. As you can see, it printed actually the same. So, it called the function and then it gave the argument there and just printed it. We can use the stacked function decorator.
That means that you will have a few decorators in the row. You will have like a first decorator, the first function and then the second one, and you will use them one by one. As you can see here, we have just two functions which are decorators,
and they are also taking function as an argument, the same scenario as the previous one, and they are just printing some text. First decorator and second decorator, and you are using two of the decorators. And how will it actually work? So, we are assigning the first decorator and then second inside,
and then as a parameter to the second, we have a function.
So, it will call the first one as a first and then the second as a second. It doesn't matter if you will use those decorators with an at symbol or you will just assign them. If you will assign, then you will clearly see how is it working.
Maybe at the beginner's time it is more clear to understand. Class decorators. They are a bit more complicated than just the function decorators. It is also a decorator. It is not a function, it is a class which is decorating something.
So, it depends. If we want to decorate a class, it is a class decorator with a function. In this case, we are decorating a class with another class. Probably we want to change the behaviour of this class, which is my class, with another class.
And that is why we just need to use class decorator. We can use a class as a decorator. For example, we want to count entries into the function and that is why we need to just adjust a little bit the function behaviour,
but it is not really possible with just a function decorators and then we will use class decorators. In this example, we can have like init when we are assigning the function and then we are writing the name where we entered and where we exited.
Let's run it and see how it works. So, we decorated function one and function two with the same decorator and then we just called function one and function two.
So, the same decorator, the same class decorator and then class as a decorator and then different functions. It saved the function name in init of the decorator and then it's printing which was entering the name of the function and then exiting the name of the function and then just running the function.
As we can see here, it's printing exactly the same for the first one and the second one. Let's go a bit deeper into decorators.
How does the decorator work? We have basic decorator here which is taking the function as an argument and then it's printing one line before calling the function and then running the function, printing line after and then returning result. It's a classic decorator which is not really changing the behaviour,
it's just printing something but still running the function and then returning the result back. But it could happen that you will change the result and you will return modified result. For example, if you need to beautify some output, if you want to print some table or something in a nice way,
then you will probably return not the original result but the nicer result which you want to decorate. Let's run the code.
It printed the same. It printed before the decorated function and then the function itself and then after the decorated function. And the name of the function which we tried to print here, it's the function name and the name is wrapped.
That means, I will show the code again, that means that we printed this name, not the original name of the function. How to get rid of it? There is a trick which you can use, wraps decorator.
It's also decorator but it will assign all the function names correctly and then you will have the correct behaviour which you expected actually. Because when you are using decorators, then be aware that you cannot rely on the name if you are not using wraps.
And in this case, the name is correct. And also the docstring is correct, it's the same from the function. So when to use decorators? I have prepared a few examples for you.
The first one is the timing with function decorators. For example, you have some functions which you want to have timing on them. And you don't want to duplicate code, you don't want to write at the very beginning, like save time and then after, subtract time and then print it again and then another one.
Sometimes it's just for debugging and then if you want to get rid of this code, then you probably need to remove all of the lines each time and it's a bit annoying. So let's run the code.
It's taking some time because we have the first function waiting for 0-2 seconds and then the second one for 1 second and then 2 and 0-3.
So in this particular example, we have the function which is doing the timing. It's printing the name of the function and then all the arguments, keyword arguments and then the timing. Basically, there is a class where you want to decorate just the function,
a single function, not the whole class and then also a function where you want to decorate only the function, then another one with an argument and then another one with an argument and keyword arguments. So the first one is taking nothing
and then the second one is taking some argument, the third one is taking two arguments and then keyword argument and then the third one is a class which is calling the class function which is decorated and then suddenly it's working. It's printing that it was waiting for 1 second and then for 2 seconds, 0-3 and then 0-2.
And for that, we use just a single piece of code here, just a function decorator which is written here and we reused with all the cases which we wanted to. And next time, if your boss is coming to your door and then asking you to add some timing on the functions,
and you're not just throwing your heads away like, oh my god, no, it's taking too much time to decorate all of the thousand million function, it will take a month. You will say, yeah, in one hour it will be done.
Timing with class decorators. For example, if you have a class and like 10,000 functions there inside and you want to decorate all of them, every single function should be timed.
Of course, you can do it like that. You can just use all of the timers to each function but sometimes it's really annoying because you have too many functions and then you want to decorate all of them. We can do it in this case as a decorator of the class. We will use the function decorator to decorate all of the functions in one class.
It's looking nice, yeah? So this is an example. We have the function, time this,
and then we have the class with all of the functions, A, B, C, which are printing something, and simply using one decorator, which is time all class methods, which is a bit more complicated than just one single decorator,
then we will have the same that we wanted to have. So it's decorating, it's starting timer, entering function A, exiting function A, and then printing the time. It looks correct.
So the next example which I have for you I used in one of my companies and it was a bit confusing because I used also decorators and late binding
and lambdas and everything all together and then suddenly my developers told me no, it's too complicated, we don't know how decorators are working and they said okay, just come to my workshop and then I will show you the magic. I will show you how is it working because we are running out of time.
So we have four functions to test, basically here three, and sometimes if you want to test functions
in the simple way as a unit testing or whatever and then you need to pass the parameter as a parameter into function and then the result which should be returned in the test and then the function which to check. You don't want to write all of the functions
for testing like a sub equals and then the function, then input, output and then the result. What I did, I just used decorators in this case which are who are creating the use cases for that.
So it looks a bit tricky and weird. It's working nice. So we have three functions which we wanted to check and the input for the function which I wrote for the decorator is this one, name of the function and then arguments
and then the result. So while import time is going, it's adding all of the tests. The class decorator which is written here is decorating the class which will add all of the tests. You can check the example later.
It's also using the lambda and late binding and I want to ask you about some magic. What will be printed here?
Any ideas?
Which one? Yes, that's correct. That's also a bit complicated. So actually I would expect here numbers from zero to zero, two, four, six
but actually we got just sixes. Why? Because at the time when we are calling the function multi-pliers then the i variable is already looked up. It's because of late binding because
the i is not binding right away when we are calling the function. It's binding it at the first. So the i looked up until the last one, until the last in our range and that's why we got all the sixes.
How to fix it? We have a few opportunities for that. We can bind it right away. So we can just bind i to i which would really expect or we can just change the behaviour of the function
to yield the value. We can try with that and that should work.
Yes, we got what we expected. So now ask yourself, are the decorators in Python gift or poison? It's on you to decide whether you will use them in your code or you will get rid of them. Just think and use them wisely.
Thank you for coming and if you have any questions and if we have some time. So is there anyone have a question? Yes.
Do you have to pay extra attention when you're decorating class methods for example will self be available to you as an argument or will it be already bound? Even in the... The function you're decorating will already be bound to the first argument self or will you have like self as an argument?
Self where in the function which you are... In the class method. In the class method of the class which you want to decorate. No, you decorate a method of the class. So if you want to decorate a function with a class or not? No. So you have your class and you want to decorate one of its methods.
So you're writing this decorator. Yes. What kind of arguments will you have access to? Will you be able to see self? So into the decorator we are passing the function itself and then it's passed with all of the parameters of it
and if you want to pass any parameters to do any kind of magic on the function which we are passing there then we need to pass there as a parameter. There is another way to decorate the decorator with another function which is taking arguments and then passing them later.
Thank you. So, okay. Hi, nice talk. Do you know by any chance what happens if you try to decorate the recursive function?
Never tried that. But you want to try. You can try. Okay, we still have it high so anyone have a question? So thanks for the talk, a quick question.
How do you debug decorators? Can you give some tips? You mean in my code? Yes, some tips. How do you debug, for example, complex decorator because it can be really painful? Yeah, it can be really painful but it's on you to decide how is it painful and how is it complex.
So my advice not to make them too complex because then you will not get afraid of feeling that something might be wrong inside because if you are calling functions in functions in functions and then you are decorating decorators few times then probably bug can be inside and then you are lost at some point.
So your suggestion is to keep them simple enough? Yes, one function at a time. Thanks. Okay. Is there a question? Okay, if there are no questions, let's thank Ms. Anna Tisha.
Thank you. Thank you.