Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace Method in Class with Reference to Itself

Assuming I can't modify or directly import a class (defined in module A) in a different module (B) say:

Part of module A:

class Tester(ParentHere):

   def run():
      print 100
      super(Tester, self).run()

How do I overwrite the run() method if I have access to the object?

For example I have,

Part of module B:

tester = factory.GetTester()
tester.run = some_method_here

How do I define some_method_here here to still call the parent class with super(Tester, self).run() if I can't directly import the Tester class or modify its original definition in module A?

For example:

def some_method_here():
    print '200 instead but do not print 100'
    super(Tester, self).run()
like image 937
Andy Avatar asked Sep 24 '26 08:09

Andy


2 Answers

You can still get a reference to Tester using the __class__ attribute of the instance. So inside, some_method_here, you could call super(self.__class__, self).run() and then run your own code. That way, whenever run is called on that specific object, it'll still execute all the code in Tester.run plus anything you add in your function.

def some_method_here(self):
    # execute all your code ...
    print '200 instead but do not print 100'
    super(self.__class__, self).run()

In your example though, when it calls super, it will still print 100 since you are executing Tester.run after your own code.

i.e. You'll see

200 instead but do not print 100
100

in the log.

If you only wanted it to print the 200 line (i.e. not execute the code in Tester.run), don't call super in the first place.

Also, super only works when calling it on classes that inherit from object so be mindful of that. If Tester doesn't inherit from object, you can't call super on it.


Just a side note, you can't directly assign a method using tester.run = some_method_here because some_method_here won't receive a self argument. You would have to do tester.run = types.MethodType(some_method_here, tester) using the types module.

like image 199
ChristianFigueroa Avatar answered Sep 26 '26 20:09

ChristianFigueroa


In your some_method_here, add a parameter tester that you will use in the super() call:

def some_method_here(tester):
    print '200 instead but do not print 100'
    super(type(tester), tester).run()

Then to get a callable with the right tester parameter plugged in, make a partial:

from functools import partial

tester = factory.GetTester()

tester_method_here = partial(some_method_here, type=tester)

tester.run = tester_method_here
like image 21
MatTheWhale Avatar answered Sep 26 '26 20:09

MatTheWhale