1

I wish to modify the method of a class by changing its behaviour. Please note that I do NOT wish to rewrite another method altogether as it is complex and involves many variables and interacts with other methods. Here is an example of what I'm trying to do:

import types
class example_class(object):
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
        self.pi = 3.14

    def example_method(self):
        print(self.a * self.b * self.c * self.pi)

#Create an instance of the object and call the method.
my_example = example_class(3, 5, 7)
my_example.example_method()

#Now I wish to change the "example_method" to add instead of multiply. 
def different_method(self, a, b, c):
    print(self.a + self.b + self.c + self.pi)

my_example.example_method() = types.MethodType(different_method(10,20,30), my_example)

I tried using types.MethodType but the above does not work. Note that I am trying to replace the example.method() with different.method(). I would like to give the method different values to calculate as well.

EDIT: Thank you to all who answered my question! You have clarified it for me and now I can monkeypatch my classes! However, I should have clarified further. I wished to modify my method to include yet another variable. So my different_method should be like this:

 #Now I wish to change the "example_method" to add instead of multiply. 
 def different_method(self, a, b, c, extra_variable):
     print(self.a + self.b + self.c + extra_variable + self.pi)

I am having difficulty adding the extra variable-if you could provide some guidance on that, I’d be very grateful!

1
  • The last line should begin my_example.example_method = ... (no parens, as it's not an invocation, it's a reference). Commented Jun 13, 2018 at 20:22

2 Answers 2

3

You're mixing up function objects, and the values returned by calls to those functions.

First, on the left side of the =, you have this:

my_example.example_method()

So you're not trying to replace the example_method attribute of my_example, you're trying to assign to whatever it returns (here, None). That makes no sense.

Then, on the right side, you're trying to build a method, not out of different_method, but out of the result of calling different_method(10,20,30). This also makes no sense.

What you want is:

my_example.example_method = types.MethodType(different_method, my_example)

Now you can call it the same as any other method:

my_example.example_method(10, 20, 30)

But, while we're at it, your different_method doesn't make much sense either. It takes parameters a, b, c, but completely ignores them, and instead just adds self.a + self.b + self.c. While this isn't illegal, it's kind of silly—and it means that the new method doesn't have the same signature as the one you were replacing, which is bound to cause confusion. So what you probably want is:

def different_method(self):
    print(self.a + self.b + self.c + self.pi)

my_example.example_method = types.MethodType(different_method, my_example)

my_example.example_method()

If you want to add different values, you'd create a new example object, just as you would when you want to multiply different values:

my_other_example = example_class(10, 20, 30)
my_other_example.example_method = types.MethodType(different_method, my_other_example)
my_other_example.example_method()

If you plan to do a lot of this monkeypatching, you may want to write a function to patch example objects:

def patch_example(example, different_method):
    example.example_method = types.MethodType(different_method, example)

… so you can do this:

my_third_example = example_class(1, 2.5, 0+1j)
patch_example(my_third_example)
my_third_example.example_method()

(However, if you really do need to do this multiple times, you probably wanted to create a subclass, or some other higher-level abstraction.)

Sign up to request clarification or add additional context in comments.

Comments

1
# first you replace the method

my_example.example_method = types.MethodType(different_method, my_example)

# then you call it
my_example.example_method(10,20,30)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.