In Python, decorators are a powerful and flexible way to modify or extend the behavior of functions or methods, without changing their actual code. A decorator is essentially a function that takes another function as an argument and returns a new function with enhanced functionality.
Decorators are often used in scenarios such as logging, authentication and memorization, allowing us to add additional functionality to existing functions or methods in a clean, reusable way.
Decorator Example:
Python
# A simple decorator function
def decorator(func):
def wrapper():
print("Before calling the function.")
func()
print("After calling the function.")
return wrapper
# Applying the decorator to a function
@decorator
def greet():
print("Hello, World!")
greet()
OutputBefore calling the function.
Hello, World!
After calling the function.
Explanation:
- decorator takes the greet function as an argument.
- It returns a new function (wrapper) that first prints a message, calls greet() and then prints another message.
- The @decorator syntax is a shorthand for greet = decorator(greet).
Let's explore decorators in detail:
Syntax of Decorator Parameters
def decorator_name(func):
def wrapper(*args, **kwargs):
# Add functionality before the original function call
result = func(*args, **kwargs)
# Add functionality after the original function call
return result
return wrapper
@decorator_name
def function_to_decorate():
# Original function code
pass
Explanation of Parameters
1. decorator_name(func):
- decorator_name: This is the name of the decorator function.
- func: This parameter represents the function being decorated. When you use a decorator, the decorated function is passed to this parameter.
2. wrapper(*args, **kwargs):
- wrapper: This is a nested function inside the decorator. It wraps the original function, adding additional functionality.
- *args: This collects any positional arguments passed to the decorated function into a tuple.
- **kwargs: This collects any keyword arguments passed to the decorated function into a dictionary.
- The wrapper function allows the decorator to handle functions with any number and types of arguments.
3. @decorator_name:
- This syntax applies the decorator to the function_to_decorate function. It is equivalent to writing function_to_decorate = decorator_name(function_to_decorate).
Higher-Order Functions
In Python, higher-order functions are functions that take one or more functions as arguments, return a function as a result or do both. Essentially, a higher-order function is a function that operates on other functions. This is a powerful concept in functional programming and is a key component in understanding how decorators work.
Key Properties of Higher-Order Functions:
- Taking functions as arguments: A higher-order function can accept other functions as parameters.
- Returning functions: A higher-order function can return a new function that can be called later.
Example of a Higher-Order Function:
Python
# A higher-order function that takes another function as an argument
def fun(f, x):
return f(x)
# A simple function to pass
def square(x):
return x * x
# Using apply_function to apply the square function
res = fun(square, 5)
print(res)
In this example, first function fun is a higher-order function because it takes another function f as an argument and applies it to the value x.
Role in Decorators:
Decorators in Python are a type of higher-order function because they take a function as input, modify it, and return a new function that extends or changes its behavior. Understanding higher-order functions is essential for working with decorators since decorators are essentially functions that return other functions.
Functions as First-Class Objects
In Python, functions are first-class objects, meaning that they can be treated like any other object, such as integers, strings, or lists. This gives functions a unique level of flexibility and allows them to be passed around and manipulated in ways that are not possible in many other programming languages.
What Does It Mean for Functions to Be First-Class Objects?
- Can be assigned to variables: Functions can be assigned to variables and used just like any other value.
- Can be passed as arguments: Functions can be passed as arguments to other functions.
- Can be returned from other functions: Functions can return other functions, which is a key concept in decorators.
- Can be stored in data structures: Functions can be stored in lists, dictionaries, or other data structures.
Python
# Assigning a function to a variable
def greet(n):
return f"Hello, {n}!"
say_hi = greet # Assign the greet function to say_hi
print(say_hi("Alice")) # Output: Hello, Alice!
# Passing a function as an argument
def apply(f, v):
return f(v)
res = apply(say_hi, "Bob")
print(res) # Output: Hello, Bob!
# Returning a function from another function
def make_mult(f):
def mult(x):
return x * f
return mult
dbl = make_mult(2)
print(dbl(5)) # Output: 10
OutputHello, Alice!
Hello, Bob!
10
Explanation:
- The code defines a greet function that returns a greeting message.
- The greet function is assigned to the say_hi variable, which is used to print a greeting for "Alice".
- Another function, apply, takes a function and a value as arguments, applies the function to the value, and returns the result.
- apply is demonstrated by passing say_hi and "Bob", printing a greeting for "Bob".
- The make_mult function creates a multiplier function based on a given factor.
Role of First-Class Functions in Decorators
- Decorators receive the function to be decorated as an argument. This allows the decorator to modify or enhance the function's behavior.
- Decorators return a new function that wraps the original function. This new function adds additional behavior before or after the original function is called.
- When a function is decorated, it is assigned to the variable name of the original function. This means the original function is replaced by the decorated (wrapped) function.
Types of Decorators
1. Function Decorators:
The most common type of decorator, which takes a function as input and returns a new function. The example above demonstrates this type.
Python
def simple_decorator(func):
def wrapper():
print("Before calling the function.")
func()
print("After calling the function.")
return wrapper
@simple_decorator
def greet():
print("Hello, World!")
greet()
OutputBefore calling the function.
Hello, World!
After calling the function.
Explanation:
- simple_decorator(func): This decorator takes the function greet as an argument (func) and returns a new function (wrapper) that adds some functionality before and after calling the original function.
- @simple_decorator: This is the decorator syntax. It applies the simple_decorator to the greet function.
- Calling greet(): When greet() is called, it doesn't just execute the original function but first runs the added behavior from the wrapper function.
2. Method Decorators:
Used to decorate methods within a class. They often handle special cases, such as the self
argument for instance methods.
Python
def method_decorator(func):
def wrapper(self, *args, **kwargs):
print("Before method execution")
res = func(self, *args, **kwargs)
print("After method execution")
return res
return wrapper
class MyClass:
@method_decorator
def say_hello(self):
print("Hello!")
obj = MyClass()
obj.say_hello()
OutputBefore method execution
Hello!
After method execution
Explanation:
- method_decorator(func): The decorator takes the method (say_hello) as an argument (func). It returns a wrapper function that adds behavior before and after calling the original method.
- wrapper(self, *args, **kwargs): The wrapper must accept self because it is a method of an instance. self is the instance of the class and *args and **kwargs allow for other arguments to be passed if needed.
- @method_decorator: This applies the method_decorator to the say_hello method of MyClass.
- Calling obj.say_hello(): The say_hello method is now wrapped with additional behavior.
3. Class Decorators
Class decorators are used to modify or enhance the behavior of a class. Like function decorators, class decorators are applied to the class definition. They work by taking the class as an argument and returning a modified version of the class.
Example:
Python
def fun(cls):
cls.class_name = cls.__name__
return cls
@fun
class Person:
pass
print(Person.class_name)
Explanation:
- add_class_name(cls): This decorator adds a new attribute, class_name, to the class cls. The value of class_name is set to the name of the class (cls.__name__).
- @add_class_name: This applies the add_class_name decorator to the Person class.
- Result: When the Person class is defined, the decorator automatically adds the class_name attribute to it.
- print(Person.class_name): Accessing the class_name attribute that was added by the decorator prints the name of the class, Person.
Common Built-in Decorators in Python
Python provides several built-in decorators that are commonly used in class definitions. These decorators modify the behavior of methods and attributes in a class, making it easier to manage and use them effectively. The most frequently used built-in decorators are @staticmethod
, @classmethod
, and @property
.
@staticmethod
The @staticmethod
decorator is used to define a method that doesn't operate on an instance of the class (i.e., it doesn't use self
). Static methods are called on the class itself, not on an instance of the class.
Example:
Python
class MathOperations:
@staticmethod
def add(x, y):
return x + y
# Using the static method
res = MathOperations.add(5, 3)
print(res)
Explanation:
- add is a static method defined with the @staticmethod decorator.
- It can be called directly on the class MathOperations without creating an instance.
@classmethod
The @classmethod decorator is used to define a method that operates on the class itself (i.e., it uses cls). Class methods can access and modify class state that applies across all instances of the class.
Example:
Python
class Employee:
raise_amount = 1.05
def __init__(self, name, salary):
self.name = name
self.salary = salary
@classmethod
def set_raise_amount(cls, amount):
cls.raise_amount = amount
# Using the class method
Employee.set_raise_amount(1.10)
print(Employee.raise_amount)
Explanation:
- set_raise_amount is a class method defined with the @classmethod decorator.
- It can modify the class variable raise_amount for the class Employee and all its instances.
@property
The @property decorator is used to define a method as a property, which allows you to access it like an attribute. This is useful for encapsulating the implementation of a method while still providing a simple interface.
Example:
Python
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value >= 0:
self._radius = value
else:
raise ValueError("Radius cannot be negative")
@property
def area(self):
return 3.14159 * (self._radius ** 2)
# Using the property
c = Circle(5)
print(c.radius)
print(c.area)
c.radius = 10
print(c.area)
Explanation:
- radius and area are properties defined with the @property decorator.
- The radius property also has a setter method to allow modification with validation.
- These properties provide a way to access and modify private attributes while maintaining encapsulation.
Chaining Decorators
In simpler terms chaining decorators means decorating a function with multiple decorators.
Example:
Python
# code for testing decorator chaining
def decor1(func):
def inner():
x = func()
return x * x
return inner
def decor(func):
def inner():
x = func()
return 2 * x
return inner
@decor1
@decor
def num():
return 10
@decor
@decor1
def num2():
return 10
print(num())
print(num2())
Similar Reads
Python Functions
Python Functions is a block of statements that return the specific task. The idea is to put some commonly or repeatedly done tasks together and make a function so that instead of writing the same code again and again for different inputs, we can do the function calls to reuse code contained in it ov
11 min read
Python def Keyword
Python def keyword is used to define a function, it is placed before a function name that is provided by the user to create a user-defined function. In Python, a function is a logical unit of code containing a sequence of statements indented under a name given using the âdefâ keyword. In Python def
6 min read
Difference between Method and Function in Python
Here, key differences between Method and Function in Python are explained. Java is also an OOP language, but there is no concept of Function in it. But Python has both concept of Method and Function. Python Method Method is called by its name, but it is associated to an object (dependent).A method d
3 min read
First Class functions in Python
First-class function is a concept where functions are treated as first-class citizens. By treating functions as first-class citizens, Python allows you to write more abstract, reusable, and modular code. This means that functions in such languages are treated like any other variable. They can be pas
2 min read
Assign Function to a Variable in Python
In Python, functions are first-class objects, meaning they can be assigned to variables, passed as arguments and returned from other functions. Assigning a function to a variable enables function calls using the variable name, enhancing reusability.Example:Python# defining a function def a(): print(
3 min read
User-Defined Functions
Python User Defined Functions
A User-Defined Function (UDF) is a function created by the user to perform specific tasks in a program. Unlike built-in functions provided by a programming language, UDFs allow for customization and code reusability, improving program structure and efficiency.Example:Python# function defination def
6 min read
Python User Defined Functions
A User-Defined Function (UDF) is a function created by the user to perform specific tasks in a program. Unlike built-in functions provided by a programming language, UDFs allow for customization and code reusability, improving program structure and efficiency.Example:Python# function defination def
6 min read
Python | How to get function name ?
One of the most prominent styles of coding is following the OOP paradigm. For this, nowadays, stress has been to write code with modularity, increase debugging, and create a more robust, reusable code. This all encouraged the use of different functions for different tasks, and hence we are bound to
3 min read
Python | How to get function name ?
One of the most prominent styles of coding is following the OOP paradigm. For this, nowadays, stress has been to write code with modularity, increase debugging, and create a more robust, reusable code. This all encouraged the use of different functions for different tasks, and hence we are bound to
3 min read
Defining a Python Function at Runtime
One amazing feature of Python is that it lets us create functions while our program is running, instead of just defining them beforehand. This makes our code more flexible and easier to manage. Itâs especially useful for things like metaprogramming, event-driven systems and running code dynamically
3 min read
Call a function by a String name - Python
In this article, we will see how to call a function of a module by using its name (a string) in Python. Basically, we use a function of any module as a string, let's say, we want to use randint() function of a random module, which takes 2 parameters [Start, End] and generates a random value between
3 min read
Explicitly define datatype in a Python function
Unlike other programming languages such as Java and C++, Python is a strongly, dynamically-typed language. This means that we do not have to explicitly specify the data type of function arguments or return values. Python associates types with values rather than variable names. However, if we want to
4 min read
Built-in and Special Functions
Python Built in Functions
Python is the most popular programming language created by Guido van Rossum in 1991. It is used for system scripting, software development, and web development (server-side). Web applications can be developed on a server using Python. Workflows can be made with Python and other technologies. Databas
6 min read
Python Lambda Functions
Python Lambda Functions are anonymous functions means that the function is without a name. As we already know the def keyword is used to define a normal function in Python. Similarly, the lambda keyword is used to define an anonymous function in Python. In the example, we defined a lambda function(u
6 min read
filter() in python
The filter() method filters the given sequence with the help of a function that tests each element in the sequence to be true or not. Let's see a simple example of filter() function in python:Example Usage of filter()Python# Function to check if a number is even def even(n): return n % 2 == 0 a = [1
3 min read
Python map() function
The map() function is used to apply a given function to every item of an iterable, such as a list or tuple, and returns a map object (which is an iterator). Let's start with a simple example of using map() to convert a list of strings into a list of integers.Pythons = ['1', '2', '3', '4'] res = map(
4 min read
reduce() in Python
The reduce(fun,seq) function is used to apply a particular function passed in its argument to all of the list elements mentioned in the sequence passed along. This function is defined in "functools" module.Basic Example:Letâs start with a simple example where we sum up all numbers in a list.Pythonfr
4 min read
Global and Local Variables
Parameters and Arguments
Python Function Parameters and Arguments
Parameters are variables defined in a function declaration. This act as placeholders for the values (arguments) that will be passed to the function. Arguments are the actual values that you pass to the function when you call it. These values replace the parameters defined in the function. Although t
3 min read
Keyword and Positional Argument in Python
Python provides different ways of passing the arguments during the function call from which we will explore keyword-only argument means passing the argument by using the parameter names during the function call.Types of argumentsKeyword-only argumentPositional-only argumentDifference between the Key
4 min read
How to find the number of arguments in a Python function?
Finding the number of arguments in a Python function means checking how many inputs a function takes. For example, in def my_function(a, b, c=10): pass, the total number of arguments is 3. Some methods also count special arguments like *args and **kwargs, while others only count fixed ones.Using ins
4 min read
Default arguments in Python
Python allows function arguments to have default values. If the function is called without the argument, the argument gets its default value.Default Arguments: Python has a different way of representing syntax and default values for function arguments. Default values indicate that the function argum
7 min read
Passing function as an argument in Python
In Python, functions are first-class objects meaning they can be assigned to variables, passed as arguments and returned from other functions. This enables higher-order functions, decorators and lambda expressions. By passing a function as an argument, we can modify a functionâs behavior dynamically
5 min read
How to get list of parameters name from a function in Python?
The task of getting a list of parameter names from a function in Python involves extracting the function's arguments using different techniques. These methods allow retrieving parameter names efficiently, whether from bytecode, introspection or source code analysis. For example, if a function fun(a,
4 min read
How to Pass Optional Parameters to a Function in Python
In Python, functions can have optional parameters by assigning default values to some arguments. This allows users to call the function with or without those parameters, making the function more flexible. When an optional parameter is not provided, Python uses its default value. There are two primar
5 min read
Return Statements
How to Pass Optional Parameters to a Function in Python
In Python, functions can have optional parameters by assigning default values to some arguments. This allows users to call the function with or without those parameters, making the function more flexible. When an optional parameter is not provided, Python uses its default value. There are two primar
5 min read
Returning Multiple Values in Python
In Python, we can return multiple values from a function. Following are different ways 1) Using Object: This is similar to C/C++ and Java, we can create a class (in C, struct) to hold multiple values and return an object of the class. Python # A Python program to return multiple # values from a meth
4 min read
Python None Keyword
None is used to define a null value or Null object in Python. It is not the same as an empty string, a False, or a zero. It is a data type of the class NoneType object. None in Python Python None is the function returns when there are no return statements. Python3 def check_return(): pass print(che
2 min read
Returning a function from a function - Python
In Python, functions are first-class objects, allowing them to be assigned to variables, passed as arguments and returned from other functions. This enables higher-order functions, closures and dynamic behavior.Example:Pythondef fun1(name): def fun2(): return f"Hello, {name}!" return fun2 # Get the
5 min read