Python Friday #205: Monkey Patching

In last week’s post we overwrote a method in the SSL module to use Feedparser with self-signed certificates. Today we take a closer look at the so called “monkey patching” and how it works under the hood.

This post is part of my journey to learn Python. You find the code for this post in my PythonFriday repository on GitHub.

 

What is monkey patching?

The term monkey patching refers to dynamic modifications of a class or module, that we can do at runtime. This allows us to modify the behaviour of a class or module in a way that we control and is a great help if we need the behaviour of the original class but with a slight modification.

For testing we can use monkey patching to change the behaviour of a class our code depends on. Instead of letting that class talk internally to the database, we can let it talk to an in-memory list. This gives us a lot of flexibility without the need to use mocks.

Be careful when you use monkey patching. It can turn ugly in no time and gives you a headache when your code works in one place of the application but not in another one.

 

A basic example of monkey patching

We can reuse the class from Python Friday #9 with an instance method:

When we run the code, it gives us this output:

Hi Johnny

So far, so unspectacular. We can now create a welcome() method that we use to replace the hi() method of our Student class:

If we run the code, we get the expected change in the behaviour:

Welcome Mark

What happens if we call the hi() method on our object that we created before we changed the behaviour? We get the new output as well:

Welcome Johnny

This behaviour was at least for me a surprise. I expected that only the instances I created after the monkey patch would have the new behaviour. But Python works differently and the replaced method on the class level applies to all instances, regardless of when they were created.

 

Monkey patch an instance

If we want to change the behaviour of only one specific instance, we need to take a different approach and use the types module:

If we run this code, only the specified instance gets the new behaviour:

Goodnight Mark
Welcome Johnny

This looks messier than the changes to the class, but the behaviour may be closer to what we expect.

 

Conclusion

Monkey patching is a tool that is widely used in the Ruby world and not so much in Python. It is good to know that this feature exists, but as we saw with the changes to the existing instances, it is a lot more complicated than what meets the eyes. Therefore, we should use it sparely and only when we want that specific behaviour.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.