Summary: in this tutorial, you’ll learn the concept of monkey patching in Python, when to use it, and how to apply it effectively.
Introduction to Python monkey patching
Monkey patching is a technique that allows you to modify or extend the behavior of existing modules, classes, or functions at runtime without changing the original source code.
Applying monkey patching
To apply the monkey patching technique, you follow these steps:
- First, identify the target that can be a module, class, method, or function you want to patch.
- Second, create your patch by writing code to add, modify, or replace existing logic.
- Third, apply the patch by using an assignment to apply it to the target. The patch will overwrite or extend the existing behavior.
While monkey patching is a powerful tool, you should use it carefully to avoid unexpected behaviors.
Monkey patching example
Suppose you have MyClass
class that only has an __init__()
method:
class Robot:
def __init__(self, name):
self.name = name
Code language: Python (python)
To extend the behavior of the Robot
class at runtime without changing the Robot
class, you can use the monkey patching technique.
Image that you need to extend a behavior that allows the Robot’s instances to speak. Here are the steps to do so:
First, define a function called add_speech
that accepts a class as the parameter:
def add_speech(cls):
cls.speak = lambda self, message: print(message)
return cls
Code language: Python (python)
The add_speech()
function adds the speak()
method by adding a speak attribute to the cls
class and assigning a lambda expression and returning the class. The lambda expression accepts a message and displays it to the console.
Second, patch the Robot
class by passing it to the add_speech()
method:
Robot = add_speech(Robot)
Code language: Python (python)
After this line of code, the Robot
class will have the speak()
method.
Note that you can use the add_speech()
function to patch any classes, not just the Robot
class.
Third, create a new instance of the Robot class and call the speak()
method:
robot = Robot('Optimus Prime')
robot.speak('Hi')
Code language: Python (python)
Put it all together:
def add_speech(cls):
cls.speak = lambda self, message: print(message)
return cls
class Robot:
def __init__(self, name):
self.name = name
Robot = add_speech(Robot)
robot = Robot('Optimus Prime')
robot.speak('Hi')Hi
Code language: Python (python)
If you run the program, you’ll see the following output:
Hi
Code language: Python (python)
Since this line of code is a decorator:
Robot = add_speech(Robot)
Code language: Python (python)
you can remove it and use the decorator syntax:
@add_speech
class Robot:
def __init__(self, name):
self.name = name
Code language: Python (python)
The new code will look like:
def add_speech(cls):
cls.speak = lambda self, message: print(message)
return cls
@add_speech
class Robot:
def __init__(self, name):
self.name = name
robot = Robot('Optimus Prime')
robot.speak('Hi')
Code language: Python (python)
When to use money patching
In practice, you should use monkey patching only when necessary because it can make code harder to understand and debug.
For example, if you use a third-party library and it has an urgent bug that you cannot wait for official release. In this case, you can use the monkey patching to apply quick fixes while waiting for a proper solution.
Another scenario is that you want to add functionality to classes that you don’t control and you cannot use other techniques like inheritance or composition, the monkey patching is useful in this case.
In practice, you’ll find monkey patching in the mock library such as the standard unittest.mock
module. The unittest.mock
module has patch()
method that temporarily replaces a target with a mock object.
Summary
- The monkey patching technique in Python allows you to dynamically modify or extend existing code at runtime without changing the original code.
- Use the monkey patching technique if you have a good reason to do so.