Open In App

Monkey Patching in Python (Dynamic Behavior)

Last Updated : 22 Aug, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

In Python, Monkey Patching refers to dynamically modifying or extending behavior of a class or module at runtime. This allows developers to change how functions, methods or classes behave without altering original source code.

Monkey patching is a powerful feature, but it should be used carefully because it can lead to unexpected behavior if not managed properly.

For Example: Suppose we have a module monk.py with a simple class:

Python
# monk.py
class A:
    def func(self):
        print("func() is being called")

Normally, calling func() would output:

func() is being called

For changing behavior at runtime we can replace func() method dynamically by assigning a new function to it:

Python
import monk

# New function to replace original func()
def monkey_f(self):
    print("monkey_f() is being called")

# Replacing the address of "func" with "monkey_f"
monk.A.func = monkey_f
obj = monk.A()
obj.func()

Output

monkey_f() is being called

Explanation:

  • A new function monkey_f is defined.
  • monkey_f is assigned to monk.A.func.
  • All instances of class A now call monkey_f() instead of original func().
  • This demonstrates Python’s ability to modify behavior dynamically at runtime.

Why Use Monkey Patching?

Monkey patching is useful in several scenarios:

  • Fixing Bugs in Third-Party Modules: Methods can be patched without modifying original library.
  • Testing and Mocking: Methods can be replaced during unit testing to simulate specific behaviors.
  • Dynamic Behavior in Frameworks: Some frameworks, such as Django, use monkey patching internally to extend classes dynamically.

Selective Monkey Patching: Instance vs. Class

Monkey patching allows modifying the behavior of classes or their instances at runtime.

Example 1: This example shows how to patch a method for a single instance without affecting other instances of same class.

Python
class B:
    def greet(self):
        print("Hello from B!")

# Create instances
b1 = B()
b2 = B()

# Define new method
def new_greet(self):
    print("Hello from monkey patch!")

# Patch only b1
b1.greet = new_greet.__get__(b1)  # Bind method to instance
b1.greet() 
b2.greet()  

Output
Hello from monkey patch!
Hello from B!

Explanation:

  • class B defines method greet and instances b1 and b2 are created.
  • New function new_greet is defined and bound only to b1 using __get__.
  • Calling b1.greet() executes patched method.
  • Calling b2.greet() executes original method, demonstrating selective patching.

Example 2: This example shows how to patch square() for one instance so it acts as a cube calculator, while other instances keep original method.

Python
class MathOps:
    def square(self, x):
        return x * x

# Create two instances
m1 = MathOps()
m2 = MathOps()

# Define a new method
def cube(self, x):
    return x * x * x

# Patch only m1
m1.square = cube.__get__(m1)  # Replace square with cube for m1
print(m1.square(3))  # Patched version → cube
print(m2.square(3))  # Original version → square

Output
27
9

Explanation:

  • MathOps.square() normally returns square of a number.
  • Two instances is created m1 and m2 and new method cube() is defined.
  • Only m1 is patched, so m1.square(3) now returns cube (27).
  • m2 keeps original behavior and returns square (9).

Note: Monkey patching can break other code and make maintenance difficult. Use it cautiously mainly for testing, quick fixes or prototyping.


Article Tags :
Practice Tags :

Explore