GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing zetcode.com — Python decorators - using decorator functions in Python Python decoratorslast modified March 21, 2024 In this article we show how to use decorator functions in Python. Python functions are first-class citizens. This means that functions have equal status with other objects in Python. Functions can be assigned to variables, stored in collections, created and deleted dynamically, or passed as arguments. A nested function, also called an inner function, is a function defined inside another function. Python decorator extends and modifies the behavior of a callable without modifying the callable itself. Decorators are functions which decorate (or wrap) other functions and execute code before and after the wrapped function runs. Python decorators are often used in logging, authentication and authorization, timing, and caching. Simple exampleIn the next example, we create a simple decorator example. main.py
#!/usr/bin/python
def enclose(fun):
def wrapper():
print("***************************")
fun()
print("***************************")
return wrapper
def myfun():
print("myfun")
enc = enclose(myfun)
enc()
The def enclose(fun): ...
The def wrapper():
print("***************************")
fun()
print("***************************")
return wrapper
The def myfun():
print("myfun")
This is a regular function to be decorated. enc = enclose(myfun) enc()
The $ python main.py *************************** myfun *************************** This is the output. The decorator adds the stars before and after the output of the regular function. Using the @ symbol
Python allows to use the main.py
#!/usr/bin/python
def enclose(fun):
def wrapper():
print("***************************")
fun()
print("***************************")
return wrapper
@enclose
def myfun():
print("myfun")
myfun()
Functionally, the example is equivalent to the previous one. Only different syntax is used. Decorating functions with parametersThe following examples show how to decorate functions which take parameters. main.py
#!/usr/bin/python
def enclose(fun):
def wrapper(val):
print("***************************")
fun(val)
print("***************************")
return wrapper
@enclose
def myfun(val):
print(f"myfun with {val}")
myfun('falcon')
In this code example, the regular function takes one argument. main.py
#!/usr/bin/python
def enclose(fun):
def wrapper(*args, **kwargs):
print("***************************")
fun(*args, **kwargs)
print("***************************")
return wrapper
@enclose
def myfun(name, age):
print(f'{name} is {age} years old')
myfun(name='Peter', age=32)
myfun('Roman', 29)
This example shows how to deal with variable number of parameters using the
Modifying dataThe decorator function can modify the data of the decorated function. main.py
#!/usr/bin/python
def uppercase(fun):
def wrapper():
res = fun()
modified = res.upper()
return modified
return wrapper
@uppercase
def gen_message():
return 'Hello there!'
msg = gen_message()
print(msg)
The def uppercase(fun):
def wrapper():
res = fun()
modified = res.upper()
return modified
return wrapper
Inside the wrapper function the text is modified and returned. $ python main.py HELLO THERE! Multiple stacked decoratorsIt is possible to apply multiple decorators on a function. main.py
#!/usr/bin/python
def strong(fun):
def wrapper():
return f'<strong>{fun()}</strong>'
return wrapper
def em(fun):
def wrapper():
return f'<em>{fun()}</em>'
return wrapper
@strong
@em
def message():
return 'This is some message'
print(message())
In the example, we apply two HTML tags on a text. $ python main.py <strong><em>This is some message</em></strong> Timing exampleIn the following example, we apply a timer decorator on a function. main.py
#!/usr/bin/python
import time
import math
import sys
sys.set_int_max_str_digits(maxdigits=90000)
def timer(func):
def wrapper(*args, **kwargs):
begin = time.time()
f = func(*args, **kwargs)
end = time.time()
print("Total time taken in : ", func.__name__, end - begin)
return f
return wrapper
@timer
def factorial(num):
return math.factorial(num)
f = factorial(4580)
print(f)
The example calculates how long the begin = time.time() Before the function is run, we get the start time. end = time.time()
print("Total time taken in : ", func.__name__, end - begin)
After the function is run, we get the end time and print the difference. The functools @wraps decorator
After applying the decorator function, the main.py
#!/usr/bin/python
from functools import wraps
def enclose(fun):
@wraps(fun)
def wrapper():
'''This is wrapper function'''
print("***************************")
fun()
print("***************************")
return wrapper
@enclose
def myfun():
'''this is myfun()'''
print("myfun")
myfun()
print(myfun.__name__)
print(myfun.__doc__)
In the example, we apply the $ python main.py *************************** myfun *************************** myfun this is myfun() The class decorator
It is possible to use classes as decorators. For this, we need to implement
the main.py
#!/usr/bin/python
import functools
class CountCalls:
def __init__(self, fun):
functools.update_wrapper(self, fun)
self.fun = fun
self.num_of_calls = 0
def __call__(self, *args, **kwargs):
self.num_of_calls += 1
print(f"Call {self.num_of_calls} of {self.fun.__name__} fun")
return self.fun(*args, **kwargs)
@CountCalls
def hello():
print("Hello there!")
hello()
hello()
hello()
In the example, we use a class decorator to count the calls of a regular function. def __init__(self, fun):
functools.update_wrapper(self, fun)
self.fun = fun
self.num_of_calls = 0
We call the def __call__(self, *args, **kwargs):
self.num_of_calls += 1
print(f"Call {self.num_of_calls} of {self.fun.__name__} fun")
return self.fun(*args, **kwargs)
We increase the $ python main.py Call 1 of hello fun Hello there! Call 2 of hello fun Hello there! Call 3 of hello fun Hello there! The @staticmethod decorator
Python has the main.py
#!/usr/bin/python
class Math:
@staticmethod
def abs(x):
if x < 0:
return -x
return x
print(Math.abs(3))
print(Math.abs(-3))
In the example, we create a static Flask decorators
Popular Python framework Flask uses decorators. For instance, the
main.py
#!/usr/bin/python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello there!'
In the example, the SourceIn this article we have worked with Python decorators. AuthorMy name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming. List all Python tutorials. |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |