0

I have an instance bear of some unknown class with a method size that returns a number. So for example:

bear.size()

will do some calculation and return a number, let's say 3.

I want to override this method so it returns double whichever number it is, so bear.size() will return 6.

When I try to implement it I get a recursion error, since the new method calls itself. So when I run:

from types import MethodType

class Animal():
    def size(self):
        return 3
bear = Animal()

def new_size(self):
    return self.size() * 2

bear.size() # returns 3. 
bear.size = MethodType(new_size, bear)
bear.size() # should return 6.

I get RecursionError: maximum recursion depth exceeded. How should I overwrite the method?

Thanks!

3
  • Assigning to bear.size creates a new, callable instance attribute (the value being a new bound method) that shadows the class attribute Animal.size. Overriding methods on a per-instance basis doesn't really make sense. Commented Jan 4, 2023 at 18:24
  • Of course there is recursion, it is calling itself over and over again, you assigned it to self.size. If you want to keep that, I guess you could use Animal.size(self) but I question the wisdom of mucking with your instance like this in the first place Commented Jan 4, 2023 at 18:25
  • @juanpa.arrivillaga it's for an edge case, so it's either this or finding and changing the original block of code, which is a central piece and would have to be compatible with the rest of the project. But it's very hacky, I agree. Commented Jan 4, 2023 at 20:57

2 Answers 2

4

You can stash the old implementation on the instance so you can call it in the overridden version.

from types import MethodType


class Animal:
    def size(self):
        return 3


bear = Animal()


def new_size(self):
    return self._old_size() * 2


bear.size()  # returns 3.
bear._old_size = bear.size
bear.size = MethodType(new_size, bear)
print(bear.size())  # should return 6.

Alternately, call the unbound original method with self:

from types import MethodType


class Animal:
    def size(self):
        return 3


bear = Animal()


def new_size(self):
    return Animal.size(self) * 2


bear.size()  # returns 3.
bear.size = MethodType(new_size, bear)
print(bear.size())  # should return 6.
Sign up to request clarification or add additional context in comments.

Comments

0

In addition to @AKX solution, you can also use decoration and decorate your function:

def double_size(fn):
    def wrapper():
        return fn() * 2
    return wrapper

bear.size()
bear.size = double_size(bear.size)
bear.size()

1 Comment

Thanks! Pretty elegant solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.