Title here
Summary here
Python provides several built-in function decorators that can be used to enhance functionality.
Some of the commonly used Python-provided function decorators, along with examples and use cases:
self
as the first argument.>>> class MyClass:
... @staticmethod
... def greet(name):
... return f"Hello, {name}!"
>>>
>>> print(MyClass.greet("Alice"))
Hello, Alice!
>>> class MathUtility:
... @staticmethod
... def add(a, b):
... return a + b
>>>
>>> print(MathUtility.add(5, 7))
12
cls
) instead of an instance (self
).>>> class MyClass:
... @classmethod
... def class_info(cls):
... return f"This is {cls.__name__} class."
>>>
>>> print(MyClass.class_info())
This is MyClass class.
>>> class MyClass:
... count = 0
...
... @classmethod
... def increment_count(cls):
... cls.count += 1
... return cls.count
>>>
>>> print(MyClass.increment_count())
1
>>> print(MyClass.increment_count())
2
>>> class Circle:
... def __init__(self, radius):
... self._radius = radius
...
... @property
... def area(self):
... return 3.14 * (self._radius ** 2)
>>>
>>> c = Circle(5)
>>> print(c.area) # (accessed as an attribute)
78.5
>>> from functools import lru_cache
>>>
>>> @lru_cache(maxsize=None) # No cache size limit
... def fibonacci(n):
... if n <= 1:
... return n
... return fibonacci(n - 1) + fibonacci(n - 2)
>>>
>>> print(fibonacci(100)) # Fast calculation due to caching
354224848179261915075
@property
decorator.>>> 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 must be positive")
>>>
>>> c = Circle(5)
>>> c.radius = 10 # Successfully sets the radius
>>> print(c.radius)
10
__name__
, __doc__
) of the original function when it is wrapped.>>> from functools import wraps
>>>
>>> def my_decorator(func):
... @wraps(func)
... def wrapper(*args, **kwargs):
... print(f"Calling {func.__name__}")
... return func(*args, **kwargs)
... return wrapper
>>>
>>> @my_decorator
... def greet(name):
... """Greet a person."""
... return f"Hello, {name}!"
>>>
>>> print(greet.__name__) # (not wrapper)
greet
>>> print(greet.__doc__) # Greet a person (not the wrapper's docstring)
Greet a person
>>> from functools import singledispatch
>>>
>>> @singledispatch
... def func(arg):
... print(f"Function for {type(arg)}: {arg}")
>>>
>>> @func.register(int)
... def _(arg):
... print(f"Function for int: {arg}")
>>>
>>> @func.register(str)
... def _(arg):
... print(f"Function for str: {arg}")
>>>
>>> func(10)
Function for int: 10
>>> func("hello")
Function for str: hello
>>> from functools import cached_property
>>>
>>> class Square:
... def __init__(self, side):
... self.side = side
...
... @cached_property
... def area(self):
... print("Computing area...")
... return self.side * self.side
>>>
>>> sq = Square(4)
>>> print(sq.area)
Computing area...
16
>>> print(sq.area) # (cached, no "Computing area...")
16
Decorator | Purpose | Use Case |
---|---|---|
@staticmethod | Defines a method that doesn’t take self or cls . | Use when a method does not require instance state. |
@classmethod | Defines a method that operates on the class (cls ). | Use when the method needs to work with the class. |
@property | Turns a method into a read-only property. | Use for computed properties. |
@property.setter | Defines a setter for a property. | Use for setting a value for a property. |
@functools.lru_cache | Caches results of expensive function calls. | Use for optimizing functions with repeated calls. |
@functools.wraps | Preserves metadata when wrapping a function. | Use when writing custom decorators. |
@functools.singledispatch | Defines a function that changes behavior based on argument type. | Use for function overloading. |
@functools.cache_property | Turns a method into a property with caching. | Use for expensive computed properties. |