This article will not make sense to all Python developers.
This only makes sense if you know how to write designers in Python. This is not a beginner’s skill. I wouldn’t even say it’s in the middle, if you do it right.
That’s why only 1% of all Python developers will learn to write them, by my calculations.
Too bad. The world’s leading Python libraries (Django, Flask, Pytest, SQLAlchemy and more) use extensive designs. So when you’re in that top 1%, you can start building huge libraries yourself.
If you are not yet in that elite 1%, there is a way to get there. But first, I’ll reveal my taxonomy of designers.
What is a decorator? This is a way to add behavior. around a set of functions or methods.
Every part of this definition is important. Read this entire article 10 times, if necessary, until you understand.
You apply a decorator to a function (or method). Actually, a bunch of them. The result is called a “decorated function”. (Or method. Just add “or method” whenever you mention a function).
“Behavior” means “lines of code”. Code that runs before the decorated function starts, or after it returns. or both. This “before and/or after” is what I mean by “around”.
The “group of” is also important. In theory, you could create a decorator and apply it to a function, but that’s a waste of time. (You’ll know why once you start typing them.) When you create a decorator, you do so with the intention of applying it to at least two functions, probably many more.
Well, the categories:
Category #1: one to one
The most useful designers fall into this category.
The idea is that every time you call the decorated function, the base function is called exactly once.
Remember, a designer adds behavior around a function. This means it is still running the target function. The decorated function is called exactly once per time.
In fact, it might be a little strange to consider not doing so. It’s a good instinct.
One of the reasons the one-on-one pattern is so helpful is that it makes sense. Results in code that is easy to think about. But sometimes it is necessary to deviate from it.
Category #2: Disconnected
You have two functions to consider:
the exposed function. The function you apply a decorator to.
and the decorated function. This is the result you get, after applying the decorator. In a sense, it creates a new function.
In the one-to-one pattern, each time you call the decorated function, the bare function is called once. But you can disconnect these two. You can write your code so that when you call the decorated function, it won’t call the base function at all.
Or call the base function sometimes, but not others.
Or maybe call the base function twice. or more.
is this a good idea? Can be. This is the basis of some very powerful patterns.
It also creates code that is difficult to think about. Because it violates the “principle of least surprise”.
So there is a compromise.
Category #3: Pure side effect
It’s interesting and weird.
But one of the most popular web frameworks in the world is fundamentally based on it.
In this type of decorator, there is no decorated function at all. Instead, the exposed function is documented as a side effect. So when you call the decorated function in your app… you’re actually calling the exposed function. But registration has other effects on other parts of the code.
This is just one way to categorize designers. There are other useful ways to break this down.
How much can you recognize in the code you write or the libraries you use every day?