Decorators Function in Python

Decorators function in Python are used to wrap or decorate any kind of function. Learn how to use them here.

Parameter Details

The function to be decorated (wrapped)

Decorators Function in Python

Decorator functions are software design patterns. They dynamically alter the functionality of a function, method, or class without having to directly use subclasses or change the source code of the decorated function. When used correctly, decorators can become powerful tools in the development process. This topic covers implementation and applications of decorator functions in Python. Decorator function

Decorators augment the behavior of other functions or methods. Any function that takes a function as a parameter and returns an augmented function can be used as a decorator.

This simplest decorator does nothing to the function being decorated. Such
minimal decorators can occasionally be used as a kind of code markers. def super_secret_function(f):
return f
@super_secret_function
def my_function():
print("This is my secret function.")

The @-notation is syntactic sugar that is equivalent to the following:

my_function = super_secret_function(my_function)

It is important to bear this in mind in order to understand how the decorators work. This “unsugared” syntax makes it clear why the decorator function takes a function as an argument, and why it should return another function. It also demonstrates what would happen if you don’t return a function:

def disabled(f):
"""
This function returns nothing, and hence removes the decorated function
from the local scope.
"""
pass
@disabled
def my_function():
print("This function can no longer be called…")
my_function()

TypeError: ‘NoneType’ object is not callable

Thus, we usually define a new function inside the decorator and return it. This new function would first do something that it needs to do, then call the original function, and finally process the return value. Consider this simple decorator function that prints the arguments that the original function receives, then calls it.

This is the decorator

def print_args(func):
def inner_func(*args, **kwargs):
print(args)
print(kwargs)
return func(*args, **kwargs) #Call the original function with its arguments.
return inner_func
@print_args
def multiply(num_a, num_b):
return num_a * num_b
print(multiply(3, 5))

Output:

Decorators function in Python: Decorator class

(3,5) - This is actually the 'args' that the function receives.
{} - This is the 'kwargs', empty because we didn't specify keyword arguments.
15 - The result of the function.

As mentioned in the introduction, a decorator is a function that can be applied to another function to augment its behavior. The syntactic sugar is equivalent to the following: my_func = decorator(my_func). But what if the decorator was instead a class? The syntax would still work, except that now my_func gets replaced with an instance of the decorator class. If this class implements the call() magic method, then it would still be possible to use my_func as if it was a function:

class Decorator(object):
"""Simple decorator class."""
def init(self, func):
self.func = func
def call(self, *args, *kwargs): print('Before the function call.') res = self.func(args, **kwargs)
print('After the function call.')
return res
@Decorator
def testfunc():
print('Inside the function.')
testfunc()
Before the function call.
Inside the function.
After the function call.

Note that a function decorated with a class decorator will no longer be considered a “function” from type-checking perspective:

import types
isinstance(testfunc, types.FunctionType)

False

type(testfunc)

Decorators function in Python: Decorating Methods

For decorating methods you need to define an additional get-method:

from types import MethodType
class Decorator(object):
def init(self, func):
self.func = func
def call(self, *args, *kwargs): print('Inside the decorator.') return self.func(args, **kwargs)
def get(self, instance, cls):

Return a Method if it is called on an instance

return self if instance is None else MethodType(self, instance)
class Test(object):
@Decorator
def init(self):
pass
a = Test()

Inside the decorator.

Warning!

Class Decorators only produce one instance for a specific function so decorating a method with a class decorator will share the same decorator between all instances of that class:

from types import MethodType
class CountCallsDecorator(object):
def init(self, func):
self.func = func
self.ncalls = 0 # Number of calls of this method
def call(self, *args, *kwargs): self.ncalls += 1 # Increment the calls counter return self.func(args, **kwargs)
def get(self, instance, cls):
return self if instance is None else MethodType(self, instance)
class Test(object):
def init(self):
pass
@CountCallsDecorator
def do_something(self):
return 'something was done'
a = Test()
a.do_something()
a.do_something.ncalls # 1
b = Test()
b.do_something()
b.do_something.ncalls # 2

Decorators function in Python: Decorator with arguments (decorator factory)

A decorator takes just one argument: the function to be decorated. There is no way to pass other arguments. But additional arguments are often desired. The trick is then to make a function which takes arbitrary arguments

and returns a decorator.

Decorator functions

def decoratorfactory(message):
def decorator(func):
def wrapped_func(*args, *kwargs): print('The decorator wants to tell you: {}'.format(message)) return func(args, **kwargs)
return wrapped_func
return decorator
@decoratorfactory('Hello World')
def test():
pass
test()

The decorator wants to tell you: Hello World

Important Note:

With such decorator factories you must call the decorator with a pair of parentheses:

@decoratorfactory # Without parentheses
def test():
pass
test()

TypeError: decorator() missing 1 required positional argument: ‘func’

Decorator classes

def decoratorfactory(*decorator_args, **decorator_kwargs):
class Decorator(object):
def init(self, func):
self.func = func
def call(self, *args, *kwargs): print('Inside the decorator with arguments {}'.format(decorator_args)) return self.func(args, **kwargs)
return Decorator
@decoratorfactory(10)
def test():
pass
test()

Inside the decorator with arguments (10,)

Decorators function in Python: Making a decorator look like the decorated function

Decorators normally strip function metadata as they aren’t the same. This can cause problems when using meta-programming to dynamically access function metadata. Metadata also includes function’s docstrings and its name. functools.wraps makes the decorated function look like the original function by copying several attributes to the wrapper function.

from functools import wraps

The two methods of wrapping a decorator are achieving the same thing in hiding that the original function has been decorated. There is no reason to prefer the function version to the class version unless you’re already using one over the other.

As a function

def decorator(func):
Copies the docstring, name, annotations and module to the decorator @wraps(func)
def wrapped_func(*args, *kwargs): return func(args, **kwargs)
return wrapped_func
@decorator
def test():
pass
test.name
'test'

As a class

class Decorator(object):
def init(self, func):
Copies name, module, annotations and docstring to the instance. self._wrapped = wraps(func)(self)
def call(self, *args, *kwargs): return self._wrapped(args, **kwargs)
@Decorator
def test():
"""Docstring of test."""
pass
test.doc

‘Docstring of test.’

Decorators function in Python: Using a decorator to time a function

import time
def timer(func):
def inner(*args, **kwargs):
t1 = time.time()
f = func(*args, **kwargs)
t2 = time.time()
print 'Runtime took {0} seconds'.format(t2-t1)
return f
return inner
@timer
def example_function():

do stuff

example_function()

Decorators function in Python:: Create singleton class with a decorator

A singleton is a pattern that restricts the instantiation of a class to one instance/object. Using a decorator, we can define a class as a singleton by forcing the class to either return an existing instance of the class or create a new instance (if it doesn’t exist).

def singleton(cls):
instance = [None]
def wrapper(*args, *kwargs): if instance[0] is None: instance[0] = cls(args, **kwargs)
return instance[0]
return wrapper

This decorator can be added to any class declaration and will make sure that at most one instance of the class is created. Any subsequent calls will return the already existing class instance.

@singleton
class SomeSingletonClass:
x = 2
def init(self):
print("Created!")
instance = SomeSingletonClass() # prints: Created!
instance = SomeSingletonClass() # doesn't print anything
print(instance.x) # 2
instance.x = 3
print(SomeSingletonClass().x) # 3
So it doesn't matter whether you refer to the class instance via your local variable or whether you create another "instance", you always get the same object

Must Read Python Interview Questions

200+ Python Tutorials With Coding Examples

Python Language Basics TutorialPython String Representations of Class Instances
Python For Beginners TutorialPython Debugging Tutorial
Python Data Types TutorialReading and Writing CSV File Using Python
Python Indentation TutorialWriting to CSV in Python from String/List
Python Comments and Documentation TutorialPython Dynamic Code Execution Tutorial
Python Date And Time TutorialPython Code Distributing using Pyinstaller
Python Date Formatting TutorialPython Data Visualization Tutorial
Python Enum TutorialPython Interpreter Tutorial
Python Set TutorialPython Args and Kwargs
Python Mathematical Operators TutorialPython Garbage Collection Tutorial
Python Bitwise Operators TutorialPython Pickle Data Serialisation
Python Bolean Operators TutorialPython Binary Data Tutorial
Python Operator Precedance TutorialPython Idioms Tutorial
Python Variable Scope And Binding TutorialPython Data Serialization Tutorial
Python Conditionals TutorialPython Multiprocessing Tutorial
Python Comparisons TutorialPython Multithreading Tutorial
Python Loops TutorialPython Processes and Threads
Python Arrays TutorialPython Concurrency Tutorial
Python Multidimensional Arrays TutorialPython Parallel Computation Tutorial
Python List TutorialPython Sockets Module Tutorial
Python List Comprehensions TutorialPython Websockets Tutorial
Python List Slicing TutorialSockets Encryption Decryption in Python
Python Grouby() TutorialPython Networking Tutorial
Python Linked Lists TutorialPython http Server Tutorial
Linked List Node TutorialPython Flask Tutorial
Python Filter TutorialIntroduction to Rabbitmq using Amqpstorm Python
Python Heapq TutorialPython Descriptor Tutorial
Python Tuple TutorialPython Tempflile Tutorial
Python Basic Input And Output TutorialInput Subset and Output External Data Files using Pandas in Python
Python Files And Folders I/O TutorialUnzipping Files in Python Tutorial
Python os.path TutorialWorking with Zip Archives in Python
Python Iterables And Iterators Tutorialgzip in Python Tutorial
Python Functions TutorialStack in Python Tutorial
Defining Functions With List Arguments In PythonWorking with Global Interpreter Lock (GIL)
Functional Programming In PythonPython Deployment Tutorial
Partial Functions In PythonPython Logging Tutorial
Decorators Function In PythonPython Server Sent Events Tutorial
Python Classes TutorialPython Web Server Gateway Interface (WSGI)
Python Metaclasses TutorialPython Alternatives to Switch Statement
Python String Formatting TutorialPython Packing and Unpacking Tutorial
Python String Methods TutorialAccessing Python Sourcecode and Bytecode
Using Loops Within Functions In PythonPython Mixins Tutorial
Python Importing Modules TutorialPython Attribute Access Tutorial
Difference Betweeb Module And Package In PythonPython Arcpy Tutorial
Python Math Module TutorialPython Abstract Base Class Tutorial
Python Complex Math TutorialPython Plugin and Extension Classes
Python Collections Module TutorialPython Immutable Datatypes Tutorial
Python Operator Module TutorialPython Incompatibilities Moving from Python 2 to Python 3
Python JSON Module TutorialPython 2to3 Tool Tutorial
Python Sqlite3 Module TutorialNon-Official Python implementations
Python os Module TutorialPython Abstract Syntax Tree
Python Locale Module TutorialPython Unicode and Bytes
Python Itertools Module TutorialPython Serial Communication (pyserial)
Python Asyncio Module TutorialNeo4j and Cypher using Py2Neo
Python Random Module TutorialBasic Curses with Python
Python Functools Module TutorialTemplates in Python
Python dis Module TutorialPython Pillow
Python Base64 Module TutorialPython CLI subcommands with precise help output
Python Queue Module TutorialPython Database Access
Python Deque Module TutorialConnecting Python to SQL Server
Python Webbrowser Module TutorialPython and Excel
Python tkinter TutorialPython Turtle Graphics
Python pyautogui Module TutorialPython Persistence
Python Indexing And Slicing TutorialPython Design Patterns
Python Plotting With Matplotlib TutorialPython hashlib
Python Graph Tool TutorialCreating a Windows Service Using Python
Python Generators TutorialMutable vs Immutable (and Hashable) in Python
Python Reduce TutorialPython configparser
Python Map Function TutorialPython Optical Character Recognition
Python Exponentiation TutorialPython Virtual Environments
Python Searching TutorialPython Virtual Environment – virtualenv
Sorting Minimum And Maximum In PythonPython Virtual environment with virtualenvwrapper
Python Print Function TutorialCreate virtual environment with virtualenvwrapper in windows
Python Regular Expressions Regex TutorialPython sys Tutorial
Copying Data In Python TutorialChemPy – Python package
Python Context Managers (“with” Statement) TutorialPython pygame
Python Name Special Variable TutorialPython pyglet
Checking Path Existence And Permissions In PythonWorking with Audio in Python
Creating Python Packages TutorialPython pyaudio
Usage of pip Module In Python TutorialPython shelve
Python PyPi Package Manager TutorialIoT Programming with Python and Raspberry PI
Parsing Command Line Arguments In Pythonkivy – Cross-platform Python Framework for NUI Development
Python Subprocess Library TutorialPandas Transform
Python setup.py TutorialPython vs. JavaScript
Python Recursion TutorialCall Python from C#
Python Type Hints TutorialPython Writing Extensions
Python Exceptions TutorialPython Lex-Yacc
Raise Custom Exceptions In PythonPython Unit Testing
Python Commonwealth Exceptions TutorialPython py.test
Python urllib TutorialPython Profiling
Web Scraping With Python TutorialPython Speed of Program
Python HTML Parsing TutorialPython Performance Optimization
Manipulating XML In PythonPython Security and Cryptography
Python Requests Post TutorialSecure Shell Connection in Python
Python Distribution TutorialPython Anti Patterns
Python Property Objects TutorialPython Common Pitfalls
Python Overloading TutorialPython Hidden Features
Python Polymorphism TutorialPython For Machine Learning
Python Method Overriding TutorialPython Interview Questions And Answers For Experienced
Python User Defined Methods TutorialPython Coding Interview Questions And Answers
Python Programming Tutorials With Examples

Other Python Tutorials

Leave a Comment