Decorating Class by Monkey Patching in Python with Example
In Python, we can decorate class using monkey patching approach. Decorating class is quite useful when we need to attach some methods to all instances of that class.
Python Source Code: Decorating Class
Let's take an example of adding log functionality to each instances of different class to illustrate decorating class using monkey patching concept.
# Decorator functions
def log_info(self):
from datetime import datetime, timezone
called_at = datetime.now(timezone.utc)
message = '{0} executed. Logged at {1}'.format(self.__class__.__name__, called_at)
return message
def logger(cls):
cls.log = log_info # monkey patching
return cls
# decorating class in action
@logger
class A:
pass
@logger
class B:
pass
# Creating instances
a1 = A()
b1 = B()
a2 = A()
b2 = B()
b3 = B()
# Printing log message
print(a1.log())
print(b1.log())
print(a2.log())
print(b2.log())
print(b3.log())
Output
A executed. Logged at 2020-05-27 09:29:52.088577+00:00 B executed. Logged at 2020-05-27 09:29:52.088577+00:00 A executed. Logged at 2020-05-27 09:29:52.089579+00:00 B executed. Logged at 2020-05-27 09:29:52.089579+00:00 B executed. Logged at 2020-05-27 09:29:52.089579+00:00
Explanation
To understand how these class are decorated, let's analyze following code:
@logger
class A:
pass
This code can be written as:
class A:
pass
A = logger(A)
So, we are passing class A
to logger function which is received in variable cls. Where it monkey patches to add log
attribute. And log
attribute is essentially log_info()
function which returns log message.
This is how log
attribute is attached to every instances of classes which are decorated.