Is it at all possible to monkey patch the value of a @property
of an instance of a class that I do not control?
class Foo: @property def bar(self): return here().be['dragons'] f = Foo() print(f.bar) # baz f.bar = 42 # MAGIC! print(f.bar) # 42
Obviously the above would produce an error when trying to assign to f.bar
. Is # MAGIC!
possible in any way? The implementation details of the @property
are a black box and not indirectly monkey-patchable. The entire method call needs to be replaced. It needs to affect a single instance only (class-level patching is okay if inevitable, but the changed behaviour must only selectively affect a given instance, not all instances of that class).
In Python, the term monkey patch refers to dynamic (or run-time) modifications of a class or module. In Python, we can actually change the behavior of code at run-time. We use above module (monk) in below code and change behavior of func() at run-time by assigning different value.
Monkey patching is a technique used to dynamically update the behavior of a piece of code at run-time. A monkey patch (also spelled monkey-patch, MonkeyPatch) is a way to extend or modify the runtime code of dynamic languages (e.g. Smalltalk, JavaScript, Objective-C, Ruby, Perl, Python, Groovy, etc.)
But you should never consider this a standard technique and build monkey patch upon monkey patch. This is considered bad because it means that an object's definition does not completely or accurately describe how it actually behaves.
Monkey patching is reopening the existing classes or methods in class at runtime and changing the behavior, which should be used cautiously, or you should use it only when you really need to. As Python is a dynamic programming language, Classes are mutable so you can reopen them and modify or even replace them.
Subclass the base class (Foo
) and change single instance's class to match the new subclass using __class__
attribute:
>>> class Foo: ... @property ... def bar(self): ... return 'Foo.bar' ... >>> f = Foo() >>> f.bar 'Foo.bar' >>> class _SubFoo(Foo): ... bar = 0 ... >>> f.__class__ = _SubFoo >>> f.bar 0 >>> f.bar = 42 >>> f.bar 42
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