Python Decorators Double Check
In my initial mad rush to learn everything Python I could, as fast as I could, I didn’t fully understand a few key concepts. I identified a couple such areas and re-studied them as it were. I decided to go all in learning these concepts so that they would be a strength instead of a weakness. The first of these was decorators, look for an upcoming post about lambda in the near future lol…
If you are interested in doing any kind of web development with Python learning about decorators is a must in my experience. If you do not understand the concept of decorators you will struggle with Flask or Django for example.
Python Decorators? Functions that modify other functions?
This was the idea I had in my head about decorators before my re-study of them. It’s not exactly wrong but it’s not a particularly helpful definition either. The main thing I needed to remember is that in Python everything is an object. Even functions. This means you can treat Python functions like other Python objects by assigning them variables, passing them to other functions, etc.
The best definition that I have cobbled together, that makes sense to me, is that a decorator is a function that wraps another function and manipulates its functionality. Python uses the @ symbol to denote decorators. Consider this kind of classic example:
def a_decorator(funk): def rapper_funk(): print ("This would be printed before the funk") funk() print ("This is gonna print after the funk") return rapper_funk def funk_needs_decorating(): print ("This is some kinda boring funk") funk_needs_decorating()
First we’re defining a function called a_decorator that takes an argument called funk. Inside a_decorator() there is another function called rapper_funk that contains 3 lines – a print statement, a function call ( to funk() – the function we used as an argument earlier…), and another print statement. Finally we are returning our rapper_funk function.
Next we define another function called funk_needs_decorating that includes a single print statement. When the next line calls it, unsurprisingly we get the printed line.
But look what happens if we assign funk_needs_decorating to a_decorator() using itself as the argument:
funk_needs_decorating = a_decorator(funk_needs_decorating) funk_needs_decorating()
What’s going on here is that we have manually created a decorator. a_decorator is wrapping the funk_needs_decorating function to modify its behavior. You can see that the print statement from the original funk_needs_decorating() function is wrapped by the 2 print statements in rapper_funk().
That awkward assignment up there can be written much more simply with decorators. Remember that decorators use the @ symbol:
@a_decorator def funk_needs_decorating(): print ("This is some kinda boring funk") funk_needs_decorating()
And you get the same results with some much cleaner code. Obviously this is a simple version, but hopefully this explains the idea of what Python’s decorators are anyway. I’ve created a Flask based web app that uses decorators in a few different ways. All things being equal I’ll post about it directly.
Here is a good video by Corey Schafer about Python decorators: