How to call the original method when it is monkey-patched?
--
Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzle Game 5 Looping
--
Chapters
00:00 Question
02:17 Accepted answer (Score 6)
03:09 Answer 2 (Score 22)
03:42 Answer 3 (Score 2)
03:54 Answer 4 (Score 1)
05:09 Thank you
--
Full question
https://stackoverflow.com/questions/8726...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #oop #python3x #monkeypatching #overriding
#avk47
ANSWER 1
Score 23
This is what we call a 'decorator' pattern. Replace the original reassignment of name to have it call a function instead, which takes the original. It then returns a new function.
def name_decorator(method):
def decorate_name(self=None):
return stuff + method(self)
return decorate_name
A.name = name_decorator(A.name)
Later, calling A.name will call decorate_name with self as the current instance and method will be available to it which points to the function at the time of the reassignment.
ACCEPTED ANSWER
Score 6
Here's a full example of what I was hinting at. Feel free to yell at me and have me merge my answers, or downvote one or whatever, just easier to provide an alternative as a new answer. I'll let the code do the talking instead of poorly explaining it. :)
## Some shared class that is used all over the place and needs to be patched.
class A(object):
def __init__(self):
self.firstname = 'Bob'
# Print my first name.
def name(self):
return self.firstname
# Use this to allow patching arbitrary methods...
@classmethod
def patch(cls, func_name):
def patch_by_name(new_func):
old_func = getattr(cls, func_name)
def patched_func(self):
return new_func(self, old_func)
setattr(cls, func_name, patched_func)
return patch_by_name
## Some other area of the code where you want to throw in a patch
class PatchedA(A): # doesn't need to subclass, but comes in handy sometimes
@A.patch('name')
def name(self, orig_func):
return 'I am ' + orig_func(self) + 'McWizwaz'
print 'Who are you, A class?'
print A().name() # prints 'I am Bob McWizwaz'
ANSWER 3
Score 2
class ABase(object):
def name(self):
pass
class A(object):
pass
class AExtension(ABase):
def name(self):
return ABase.name(self)
A.name = AExtension.name
ANSWER 4
Score 1
One option that might not always be the best in a language like Python is to use the @override decorator from this non-standard package. But this is a viable option only if your two functions work on different types or different number of arguments. Other than that, there's not much you can do, besides renaming your function.