How To Use and Implement Function Decorators in Python 🐍

pwned
2 min readDec 12, 2021
Image from: https://pixabay.com/de/photos/code-programmierung-python-1084923/

By definition, a decorator is a function that takes another function as its input, with the purpose of implicitly extending its behavior without explicitly modifying it. As a Python developer you may have seen such decorators when dealing with classes, as shown in the example below.

class Dog:    def __init__(self, name):
self.name = name
def say_my_name(self):
print("Wuff, my name is {}".format(self.name))
@staticmethod
def say_wuff():
print("Wuff!")
d = Dog("Bob")
d.say_my_name() # Wuff, my name is Bob
Dog.say_wuff() # Wuff!

In Python we usually use decorators when declaring class methods as staticmethods, which are methods belonging to a class rather than an instance of a class. This method is accessible to every instance of it, whereas methods defined in an instance are only able to be accessed by that member of a class. Sounds pretty confusing but in fact this means that static methods can be called without the need of instantiating the class.

As Linus Torvalds teached us:

Talk is cheap, show me the code

def uppercase_decorator(function):
def wrapper():
func = function()
make_uppercase = func.upper()
return make_uppercase
return wrapper @uppercase_decorator
def say_hello_world():
return "Hello, World!"
def main():
print(say_hello_world()) # HELLO, WORLD!
if __name__ == '__main__':
main()

An interesting aspect here is that we can tag a method with as many decorators as we want. Whether it makes sense to use n β†’ ∞ decorators on a single method is of course completely out of the question, but from a technical point of view it is realizable.

def uppercase_decorator(function):
def wrapper():
func = function()
make_uppercase = func.upper()
return make_uppercase
return wrapperdef split_decorator(function):
def wrapper():
func = function()
make_uppercase = func.split(" ")
return make_uppercase
return wrapper@split_decorator
@uppercase_decorator
def say_hello_world():
return "Hello, World!"
def main():
print(say_hello_world()) # ['HELLO,', 'WORLD!']
if __name__ == '__main__':
main()

Have in mind that the order of the tags matters, so depending on how your decorator sequence looks like it might happen that you run in errors or unexpected side effects. For example if I change lines 20 and 21 you will be confronted with the following error message: AttributeError: β€˜list’ object has no attribute upper. Doing so would result in the split decorator being applied first and the upper decorator being applied applied afterwards. Decorators are applied from bottom to top.

--

--