Home/Blog/Programming/Using Python Class Decorators Effectively
Home/Blog/Programming/Using Python Class Decorators Effectively

Using Python Class Decorators Effectively

2 min read
Jul 03, 2023
content
Decorators
Python Class Decorators
Some Built-in Class Decorators
cache/ memoize
property
cached_property
Conclusions

Become a Software Engineer in Months, Not Years

From your first line of code, to your first day on the job — Educative has you covered. Join 2M+ developers learning in-demand programming skills.

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!

Video thumbnail

Decorators#

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
@debug
def typical_crunching_function(name, city):
return 'You are '+ name + ' from '+ city
typical_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.

Python Class Decorators #

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 = function
def __call__ (self, name):
# Adding Excellency before name
name = "Excellency " + name
self.function(name)
# Saluting after the name
print("Thanks "+ name+ " for gracing the occasion")
@Accolade
def 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

Some Built-in Class Decorators#

Here are some of the built-in class decorators.

cache/ memoize #

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
@cache
def factorial(n):
return n * factorial(n-1) if n else 1
print(factorial(10))

property#

This decorator allows to add setter and getter functions to a property in a class.

class Pencil:
def __init__(self, count):
self._counter=count
@property
def counter(self):
return self._counter
@counter.setter
def counter(self, count):
self._counter = count
@counter.getter
def counter(self):
return self._counter
HB = Pencil(100)
print (HB.counter)
HB.counter = 20
print (HB.counter)

cached_property#

This decorator allows the property of a class to be cached. This is equal to nesting the two decorators.

@cached
@property
def counter:
return self._counter

Conclusions#

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

Cover
Python 201 - Interactively Learn Advanced Concepts in Python 3

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.

11hrs
Intermediate
250 Playgrounds
22 Quizzes


Written By:
Zahid Irfan
Join 2.5 million developers at
Explore the catalog

Free Resources