What Are Duck Typing and Monkey Patching in Python?
One reason why we say Python is flexible
This isn’t an article about animals, although it’s not too common to have three animal names in a headline. Today, I would like to discuss duck typing and monkey patching in Python. Both features are critical to making Python a flexible language to work with for general purposes.
After reading this article, I hope that you’ll have an intuitive idea about how duck typing and monkey patching work in Python. Let’s get started!
The term duck typing isn’t something new to many programmers — especially if you have some background in dynamic programming languages. However, it was not invented by computer scientists. Let’s see its general definition:
“If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.” — Wikipedia
This is a form of abductive reasoning, and it means that we draw our conclusion of one’s identity only based on their external appearance and behaviors instead of their actual types. In programming languages, duck typing represents an implementation pattern of defining how particular objects behave without worrying about the types of the class. It may sound too abstract, but with a concrete example, you’ll find it not hard at all.
First, we’ll create a “true” duck class that we’ll use as a benchmark to define a duck’s behaviors. As shown below, the
Duck class has two instance methods —
quack() (two behaviors that you can expect with ducks):
As an instance object of the
Duck class, we can verify that a duck is able to behave like a duck. It can swim and quack. As shown below, we first create the
duck_testing function to check whether a presumed duck can swim and quack. As expected, the
duck instance does just what it’s supposed to and passes the duck typing test:
Did you notice that I actually checked the type of the
duck instance object using the introspection function
isinstance? By verifying that the presumed duck is an instance of the
Duck class, we are sure that it will pass the duck typing test. However, it’s tedious to check the object of interest’s type to expect its behavior, which is exactly what duck typing tries to avoid. The key to duck typing is that we don’t care about the object’s type. As long as it can swim and quack (or any other defined behaviors or methods), we consider it to be a duck (or any concerned type).
Let’s see how duck typing works beyond the
Duck class that we’ve been talking about. For the sake of contrast, I’ll create two custom classes:
As shown above, the
ToyDuck class has both the
quack() methods implemented. Thus, according to duck typing, we should expect it to pass the duck typing test. On the other hand, the
Human class only has the
swim() method and thus won’t pass the duck typing test to qualify as a duck. Let’s verify our predictions next:
As expected, a toy duck can swim and quack, while a human can only swim. The
human instance object isn’t considered a duck-like object. Notably, neither the
toy_duck nor the
human objects are an instance object of the original
Duck class. It’s just the supported behaviors (i.e. swim and quack) that make the
toy_duck a duck-like object and pass the duck typing test. It’s the key to implementing duck typing.
The term monkey patching has a very interesting name. According to Wikipedia, the monkey patch is probably related to the earlier term “guerrilla patch,” which referred to changing code sneakily. Given guerrilla’s homophonous relationship with gorilla and gorilla’s relationship with monkey (both being primates), the monkey patch was engendered. In terms of its specific conceptualization in the world of programming, it’s defined as such:
“A monkey patch is a way for a program to extend or modify supporting system software locally (affecting only the running instance of the program).” — Wikipedia
As a dynamic language, Python allows us to use monkey patching in our coding by extending specific modules or classes without modifying their original implementations. In this section, we want to make instances of the
Human class (defined above) able to behave like a duck. I know it’s weird, but just think about Donald Duck as a human.
To understand how monkey patching works mechanistically, let’s step back and see how Python classes work. As we all know, Python is an object-oriented language that operates by treating everything as objects, including modules and classes. To provide a proof of concept, we’ll just apply monkey patching to a custom class. Before we dive into the details, let’s see a simplified Python class:
It’s definitely not a fancy class, with just a class attribute and an instance method (if you don’t know about the
self argument, check out this article). One thing to note is that we can access
__dict__ attribute, which lists all the attributes of this class, including the
bar. As mentioned previously, Python classes are also objects, which means that we can dynamically update their attributes even during the runtime. By the way, that’s exactly what monkey patching is all about.
As you can see in the code snippet above, we directly set one attribute and one function to the class object. As a result, the updated class’
__dict__ attribute reveals that
bar2 are indeed “patched” to the original class. Importantly, we can access
attr2 as we normally do with the predefined attributes (e.g.
Now that we know how monkey patching works with a generic class, let’s try it with the
Human class. Just a friendly reminder: The desired feature is to make a human object quack so that it can pass the duck typing test. Importantly, we’re not going to change the original class. As shown below, we define a function named
quack and set this function as the
quack attribute of the
One thing to note is that the defined
quack function has an argument that doesn’t seem to be used, but it’s essential to have it. Because the
quack function is an instance method, which will always have an argument (we used
self in this class, but you can call it whatever you want) referring to the instance object. If you’re still confused about the
self argument, please check out my previous articles.
As you can see, after the monkey patching, the instance object of the
Human class is successfully able to pass the duck typing test. Again, this pass doesn’t involve changing the implementation of the original
Human class. Instead, we “patch” these features outside of the class. That’s the beauty of this dynamic feature.
In this article, we reviewed how duck typing and monkey patching work in Python. Here’s a quick recap of these two terms:
- Duck typing is a means to design a class to have the desired behaviors without subclassing or implementing a protocol, interface, or abstract base classes. It’s OK if you don’t know these terms. You can still use duck typing. Again, the key is to implement the required methods and attributes for the desired behaviors.
- Monkey patching is an extension mechanism that allows us to implement additional features of existing modules and classes without modifying the original implementations. However, use it with caution because different parts of your code that patch the same module/class will result in unexpected behaviors by stepping on each other’s toes.