Python
Object-Oriented Programming
Python Methods
Python Instances
Coding Techniques

Adding a method to an existing object instance in Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Python, you can add behavior to one specific object instance at runtime instead of changing the whole class. The important detail is that a plain function assigned to an instance is just an attribute until it is bound correctly as a method. If you want the function to receive self automatically, bind it with types.MethodType or the descriptor protocol.

Instance-Level Method Injection

Suppose you have a class and want one object to gain a custom method.

python
1class Dog:
2    def __init__(self, name):
3        self.name = name
4
5    def bark(self):
6        return f"{self.name} says woof"
7
8
9def howl(self):
10    return f"{self.name} says awoooo"

If you assign howl directly, Python treats it as a plain function object stored on the instance.

python
fido = Dog("Fido")
fido.howl = howl

Calling fido.howl() now fails because the function is not automatically bound to fido.

Bind the Function as a Method

The cleanest way is types.MethodType.

python
1import types
2
3fido = Dog("Fido")
4fido.howl = types.MethodType(howl, fido)
5
6print(fido.howl())

Output:

text
Fido says awoooo

Now self is supplied automatically because the function has been bound to that specific instance.

Alternative: Use __get__

The descriptor protocol can do the same job more explicitly.

python
fido = Dog("Fido")
fido.howl = howl.__get__(fido, Dog)
print(fido.howl())

This works because functions in Python are descriptors. Calling __get__ binds the function to the instance and returns a bound method.

Why You Might Do This

Adding a method to one instance can be useful for:

  • tests and quick mocks
  • runtime customization of one object
  • attaching behavior in plugin-style systems
  • experiments in interactive sessions

But it is usually not the best design for ordinary application code. If every instance should gain the behavior, modify the class instead.

Add a Method to the Class When It Belongs Everywhere

If all instances need the method, patch the class, not one object.

python
1Dog.howl = howl
2
3rex = Dog("Rex")
4print(rex.howl())

That affects every current and future Dog instance, which is often what you actually want.

Watch Out for __slots__

Not every instance can accept new attributes. If the class defines __slots__ without a __dict__, arbitrary instance attributes cannot be added.

python
1class Cat:
2    __slots__ = ("name",)
3
4    def __init__(self, name):
5        self.name = name

An object of Cat cannot accept a new meow_loudly method unless the class design allows dynamic attributes.

Treat It as a Tool, Not a Default Pattern

Per-instance method injection is essentially a form of monkey-patching. It is powerful, but it can surprise readers because the object's interface is no longer obvious from the class definition alone.

That tradeoff is acceptable in tests, adapters, and debugging sessions. It is much riskier in long-lived production code where maintainability matters more than runtime cleverness.

Common Pitfalls

  • Assigning a plain function to an instance and expecting automatic self binding.
  • Using per-instance method injection when the behavior really belongs on the class.
  • Forgetting that __slots__ may prevent adding new attributes.
  • Making production code harder to reason about with too much runtime patching.
  • Confusing instance attributes with bound methods.

Summary

  • You can add a method to one Python instance at runtime.
  • Use types.MethodType or __get__ to bind the function correctly.
  • Assigning the function directly is not enough if you want automatic self handling.
  • Patch the class instead if the method should exist on every instance.
  • Be aware that __slots__ can prevent per-instance method injection.

Course illustration
Course illustration

All Rights Reserved.