sirikon.me

0003 Patching classes in Python

Oh, so you found yourself needing to patch a class in Python? again? And some neckbeard is telling you on the internet you shouldn't do it?

I'm about to give you a loaded gun buddy.

class Animal:
    def announce(self):
        print("I'm " + self.__class__.__name__)


class Goose(Animal):
    def honk(self, name: str):
        super().announce()
        print(f"HONK. HEY {name.upper()}. GET OFF MY LAWN.")

    def do_your_thing(self):
        self.honk("Stranger")


class AmericanGoose(Goose):
    def honk(self, name: str):
        super().honk(name)
        print("BANG. BANG.")


g = AmericanGoose()
g.do_your_thing()
I'm AmericanGoose
HONK. HEY STRANGER. GET OFF MY LAWN.
BANG. BANG.

Let's say you want to make geese more polite.

def make_geese_polite():
    # pick the old method if you need it.
    old_honk = Goose.honk

    # define __class__ pointing to the class to patch, so calls
    # to super() work.
    __class__ = Goose

    def new_honk(self, name: str):
        print("-- Polite Goose")
        super().announce()
        print(f"Good evening {name}. May you please get off my lawn.")
        print("-- Original Goose")
        # call the old method by passing `self`
        old_honk(self, name)
        print("-- End")

    Goose.honk = new_honk


make_geese_polite()
g.do_your_thing()
-- Polite Goose
I'm AmericanGoose
Good evening Stranger. May you please get off my lawn.
-- Original Goose
I'm AmericanGoose
HONK. HEY STRANGER. GET OFF MY LAWN.
-- End
BANG. BANG.

Use this power wisely.

EDIT: Replacing "gooses" with "geese" because I'm an uneducated fuck.