Decorating Classes
The above section shows how decorators help in decorating functions. We have seen that decorators are callable that accepts and returns a callable. Since classes are callable, decorators are also used to decorate classes. Some of the uses of decorating classes are:
- Addition or enhancement of attributes
- Attribute interaction
- Alter the API of a class (alter the way of declaring classes and its instance use)
Let’s go through how to decorate a function using class.
class MyDecorator: def __init__( self , function): self .function = function def __call__( self ): print ( "Inside Function Call" ) self .function() @MyDecorator def function(): print ( "w3wiki" ) def main(): function() if __name__ = = "__main__" : main() |
Output:
Inside Function Call w3wiki
Let’s look into an another example. Below code, sort the instance based on their creation time. Here we require three additional attributes- the instantiation timestamp, __lt__ and __gt__ methods.
import functools import time def sort_by_creation_time(cl): org_init = cl.__init__ # Enhance the class to store the creation # time based on the instantiation. @functools .wraps(org_init) def new_init( self , * args, * * kwargs): org_init( self , * args, * * kwargs) self ._created = time.time() # __lt__ and __gt__ methods return true or false # based on the creation time. cl.__init__ = new_init cl.__lt = lambda self , other: self ._created < other._created cl.__gt__ = lambda self , other: self ._created > other._created return cl @sort_by_creation_time class Sort( object ): def __init__( self , identifier): self .identifier = identifier def __repr__( self ): return self .identifier def main(): first = Sort( 'Python' ) second = Sort( 'Data Analysis' ) third = Sort( 'Machine Learning' ) sortables = [third, first, second] print ( sorted (sortables)) if __name__ = = "__main__" : main() |
Output
[Python, Data Analysis, Machine Learning]
new_init
, its primary responsibility is to run the wrapped function and also add an extra functionality to the wrapped function. The @functools.wraps(org_init)
update the wrapper function to reflect the look of wrapped function. Check functools for detail understanding.
@functools .wraps(org_init) def new_init( self , * args, * * kwargs): # calls the init method of class org_init( self , * args, * * kwargs) # add an extra attribute and store # creation time self ._created = time.time() # reference of new_init is assigned to # __init__ method and executes when # callable creates the class object. cl.__init__ = new_init |
Python Decorators: A Complete Guide
A decorator is a design pattern tool in Python for wrapping code around functions or classes (defined blocks). This design pattern allows a programmer to add new functionality to existing functions or classes without modifying the existing structure. The section provides an overview of what decorators are, how to decorate functions and classes, and what problem can it solve.