Python is the only language with idioms. This enhances its readability and, perhaps, its beauty. Decorators follow the Zen of Python, aka the ‘Pythonic’ way.
"There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you’re Dutch."
Decorators have been available since Python 2.2. They were enhanced with the PEP318.
Below is a beginner-focused tutorial for how to use decorators. If you prefer to run the code samples yourself, keep reading!
A decorator
(not to be confused with the decorator pattern) is a method to add/change the behavior of functions without changing the original function. In Python, a decorator is a design pattern that allows you to modify the functionality of a function by wrapping it in another function. The outer function is called the decorator, which takes the original function as an argument and returns a modified version.
Let us learn by example. Here we declare a debug
decorator. It helps print the output of the function instead of adding print commands, which later becomes unwieldy and, at times, irritatingly tedious to remove.
def debug(function):def wrapper(name, address):print ('Debugging:')func = function(name, address)print (func)return wrapper@debugdef typical_crunching_function(name, city):return 'You are '+ name + ' from '+ citytypical_crunching_function('John','Los Angeles')
Here we have defined the decorator in line 1-6
and applied to the function typical_crunching_function
in line 8
using the @ syntax.
Class decorators were introduced in PEP3129. This was after a lot of resistance from the community which preferred metaclasses
. The main purpose is to extend the ability of decorating functions to classes.
Here is an example of a class decorator enhancing the functionality of a function.
class Accolade:def __init__(self, function):self.function = functiondef __call__ (self, name):# Adding Excellency before namename = "Excellency " + nameself.function(name)# Saluting after the nameprint("Thanks "+ name+ " for gracing the occasion")@Accoladedef simple_function(name):print (name)simple_function('John McKinsey')
Here the Cleaner
class is defined which can be used to perform pre-processing and post-processing to the simple_function. In this example we are simply adding Excellency
to the string name
and after printing the name we thanks for gracing the occasion. This simple example demonstrates that we can use class decorators to easily perform pre-processing and post-processing on the function arguments. These pre-processing tasks could be any of the below not limited to these.
Adding timing information
connecting to databases
closing connections
memoizing storage
Here are some of the built-in class decorators.
Please note that its only available in Python >= 3.9. This allows caching previous values and reusing them instead of recalculating.
from functools import cache@cachedef factorial(n):return n * factorial(n-1) if n else 1print(factorial(10))
This decorator allows to add setter and getter functions to a property in a class.
class Pencil:def __init__(self, count):self._counter=count@propertydef counter(self):return self._counter@counter.setterdef counter(self, count):self._counter = count@counter.getterdef counter(self):return self._counterHB = Pencil(100)print (HB.counter)HB.counter = 20print (HB.counter)
This decorator allows the property of a class to be cached. This is equal to nesting the two decorators.
@cached@propertydef counter:return self._counter
Decorators are very convenient and elegant tools, However they are also very prone to errors. So they should be used with a lot of care.
Interactively Learn Advanced Python Concepts
This course will help you take the next level in your programming journey. It will demonstrate the ways you can use Python in your day-to-day work. We will cover intermediate and some advanced-level material in this course. Python 201 is split into four parts; Part one covers intermediate modules. Part two covers topics such as Unicode, generators, and iterators. Part three covers web-related tasks with Python. Part four covers testing code.
Free Resources