Home > other >  How to change one class in an external package for my use?
How to change one class in an external package for my use?

Time:03-28

I use an external pacakge which I bring in via pip.

This package has a structure as follows:

class OuterThing:
  field: Innerthing
  def outer_method1(self...

class InnerThing():
   def inner_method1(self,...
   def inner_method2(self,...
   def inner_method3(self,...

I instantiate only OuterThing objects (which then internally instantiate InnerThing objects).

I want the inner thing objects to have all the normal fields and methods, just inner_method1 I need to customise a bit for my use.

What is the shortest way (i.e. the way with the least code) to do this?

I do not want to copy the whole package into my source tree if possible, just "inject" the changes at runtime (but possibly before all instantiations) to the specified method in InnerThing.

CodePudding user response:

Python allows you to Monkey Patch code simply by assigning a different function pointer to the function you're trying to replace. This can be done as long as you can grab a reference to the instance of InnerThing at runtime.

In your case, it seems like OuterThing does have a reference to InnerThing so you can do something like this:

def your_implementation_of_inner_method1(self, ...):
   # Do stuff

outerThing = OuterThing()
outerThing.field.inner_method1 = your_implementation_of_inner_method1

If you want to dig deeper as to why this is possible, I recommend having a look at the Python documentation for classes. The tl;dr is that methods are actually objects and are stored as fields in instances of the class.

CodePudding user response:

In Python, a method is just an attribute of the class object that happens to be a function having self as its first parameter. That means that you can easily replace it by your own function, provided you keep the same signature. You can even call the original method from your own one:

# after having imported InnerThing
_orig_inner_method1 = InnerThing.inner_method1

def _patched_inner_method1(self, ...):
    # your own code
    ...
    _orig_inner_metho1(self, ...)   # eventually call the original method
    ...

InnerThing.inner_method1 = _patched_inner_method1

From that point, any InnerThing object created will use your patched method.

  • Related