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

Question:

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.

Asked By: halloleo

||

Answers:

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.

Answered By: Rayan Hatout

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_method1(self, ...)   # eventually call the original method
    ...

InnerThing.inner_method1 = _patched_inner_method1

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

Answered By: Serge Ballesta
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.