Given a class A
I can simply add an instancemethod a
via
def a(self):
pass
A.a = a
However, if I try to add another class B
's instancemethod b
, i.e. A.b = B.b
, the attempt at calling A().b()
yields a
TypeError
: unbound methodb()
must be called withB
instance as first argument (got nothing instead)
(while B().b()
does fine). Indeed there is a difference between
A.a -> <unbound method A.a>
A.b -> <unbound method B.b> # should be A.b, not B.b
So,
Curiously enough, this no longer fails in Python3...
monkeypatch can be used to patch functions dependent on the user to always return a specific value. In this example, monkeypatch. setattr is used to patch Path. home so that the known testing path Path("/abc") is always used when the test is run.
Etymology. The term monkey patch seems to have come from an earlier term, guerrilla patch, which referred to changing code sneakily – and possibly incompatibly with other such patches – at runtime. The word guerrilla, nearly homophonous with gorilla, became monkey, possibly to make the patch sound less intimidating.
While working on a real-time project, it might so happen that the third-party library is not working well. In order to change it from our project end, monkey patching becomes very useful. With monkey patching, we tend to change a particular code at runtime so that it behaves differently.
In Ruby, a Monkey Patch (MP) is referred to as a dynamic modification to a class and by a dynamic modification to a class means to add new or overwrite existing methods at runtime. This ability is provided by ruby to give more flexibility to the coders.
Let's:
class A(object): pass
class B(object):
def b(self):
print 'self class: ' + self.__class__.__name__
When you are doing:
A.b = B.b
You are not attaching a function to A, but an unbound method. In consequence python only add it as a standard attribute and do not convert it to a A-unbounded method. The solution is simple, attach the underlying function :
A.b = B.b.__func__
print A.b
# print: <unbound method A.b>
a = A()
a.b()
# print: self class: A
I don't know all the difference between unbound methods and functions (only that the first contains the second), neither how all of that work internally. So I cannot explain the reason of it. My understanding is that a method object (bound or not) requires more information and functionalities than a functions, but it needs one to execute.
I would agree that automating this (changing the class of an unbound method) could be a good choice, but I can find reasons not to. It is thus surprising that python 3 differs from python 2. I'd like to find out the reason of this choice.
When you take the reference to a method on a class instance, the method is bound to that class instance.
B().b
is equivalent to: lambda *args, **kwargs: b(<B instance>, *args, **kwargs)
I suspect you are getting a similarly (but not identically) wrapped reference when evaluating B.b. However, this is not the behavior I would have expected.
Interestingly:
A.a = lambda s: B.b(s)
A().a()
yields:
TypeError: unbound method b() must be called with B instance as first argument (got A instance instead)
This suggests that B.b
is evaluating to a wrapper for the actual method, and the wrapper is checking that 'self' has the expected type. I don't know, but this is probably about interpreter efficiency.
It's an interesting question though. I hope someone can chime in with a more definitive answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With