Can Monkey Patching Replace Existing Function Definition In A Class?
Solution 1:
Your only problem is that you aren't defining foo correctly in the first place. It needs to take an explicit argument for the instance calling it.
classA(object):
def__init__(self)
self.x = 2deffoo(self):
print(self.x)
deffoo(this):
print(this.x + 3)
A.foo = foo
a = A()
a.foo() # outputs 5 in Python 2 and Python 3In a very real sense, monkey patching is how classes are created in the first place. A class statement is almost just syntactic sugar for the following code:
deffoo(self):
print(self.x)
A = type('A', (object,), {'foo': foo})
del foo
It's not too much of a simplification to image the definition of type being something like
deftype(name, bases, d):
new_class = magic_function_to_make_a_class()
new_class.name = name
new_class.bases = bases
for k, v in d.items():
setattr(new_class, k, v)
return new_class
Solution 2:
I hope I understand what you are trying to do here. This would work in Python 3:
class A():
def foo():
print('2')
def foo():
A.foo = lambda: print('5')
A.foo() # Print '2'foo() # Assign the new method
A.foo() # Prints '5'In Python 2 however there are several caveats.
printis not a method as it is in Python 3 (see here: Why doesn't print work in a lambda?)You can't just call unbound messages (see here: In Python, can you call an instance method of class A, but pass in an instance of class B?)
So you have to do it like this:
from __future__ import print_function
classA():
deffoo():
print('2')
deffoo():
A.foo = lambda: print('5')
A.foo.__func__() # Print '2'
foo() # Assign the new method
A.foo.__func__() # Prints '5'Edit: After seeing your question in the comment I think you actually want something different. Which is this:
classA():
deffoo(self):
print'2'deffoo(self):
print'5'
a = A()
a.foo() # Print '2'
A.foo = foo # Assign the new method
a.foo() # Prints '5'This works just fine in Python 2.
The self is a reference to the current instance the method is bound to. It is not used when you just call something like print which access any properties or methods attached to that instance. But for a different case please have a look at the following example:
classA():
msg = "Some message"deffoo(self):
print self.msg
defbar(self):
self.msg = "Some other message"
a = A()
a.foo() # Print old msg
A.bar = bar # Assign the new method
a.bar() # Assigns new message
a.foo() # Prints new messageAlso as chepner points out in a comment under his post:
The name self isn't special; it's just a convention. You could use this if you really wanted to, and it doesn't need to be the same name in both functions defined here. What is important is that the first argument to a function used as an instance method will be a reference to the calling object. a.foo() is almost exactly the same as A.foo(a)
Post a Comment for "Can Monkey Patching Replace Existing Function Definition In A Class?"