For more information on topics covered in this lesson, check out these resources:
Taking and Returning Functions With Decorators
00:07 A decorator function takes a function object as an argument and returns a function object. The decorator processes the decorated function in some way and then returns either that function object or replaces it with a function or other type of callable object. Decorators are useful when you need to add extra logic to an existing function but you don’t want to modify the original function itself.
00:35 There exist many decorators in Python. With classes and objects, you’ll see decorators for class methods, static methods, and properties. Web frameworks use decorators to control access, and you’ll see decorators and other libraries as well.
And you can write your own. For example, you might want to code a function to log its function calls, validate the arguments to a function, or measure the execution time of a function. Again, any situation where you need to add additional logic to a function without directly changing that function is a good place to use a function decorator. As an example, suppose you want to create a function that finds the execution time of another function. Based on what you saw in the last lesson, you could create a function to do the timing, which takes as an argument the function you want to time. Since it’s using timing functions, it needs to import the
01:39 I’ll have more to say about that near the end of the lesson. Next is to define a function whose purpose is to time the execution of another function. That function that you wish to time will be used as an argument to this function.
In it is an inner function, which will handle all of the processing. We find the system time that the function begins, then call the function provided as an argument to the outer function, allowing you to use any positional or keyword arguments that function was provided and then saving its return value to
The higher-ordered function returns this inner-function object, which remembers what function was provided as an argument much in the same way
multiply() from the previous lesson remembered the
2 and the
I’ll explain what that means in a moment. In this case, it’s a function to compute the mean of a set of data. We have a time delay of
1 second, just to make determining the execution time more interesting.
Here’s where that
@ notation comes in. When you indicate that
my_timer() is decorating
delayed_mean(), Python creates the function produced by
my_timer() passed with
delayed_mean as an argument and saves that back to the name
04:30 It took a little bit of time to run, but eventually the inner function produced the execution time of 1.00 something. And that’s going to vary from one function call to the next, depending on what your computer happens to be doing at the same time.
So, what’s happening? Python runs decorator functions as soon as you import or run a module or script. In this case, when you called
delayed_mean(), you were really calling the object returned from
my_timer(), which here was the function object
A decorator function essentially wraps itself around the function it decorates. If there was another function whose execution time you were interested in, all you would have to do is decorate that one with the
@my_timer decorator as well.
time(), we use the function
time() to help compute the execution time of a function call. This function is in a module called
time, which you saw me import, that provides a set of time-related functions.
time() function returns the number of seconds that has elapsed since some time designated as time equals zero on your computer. This time zero is referred to as the epoch time and its precise date and time depend on your computer and operating system. Finally, here are some additional Real Python resources you may want to look at for more detailed information on some of the material presented here.
Become a Member to join the conversation.