I have a class instance with several properties:
class MyClass(object):
@property
def func(self):
return [1,4,5]
@property
def func2(self):
return 6
I would like to dynamically change a property from a user supplied new method, for example:
obj = MyClass()
def patch_property(name, new_return):
source = '@property\ndef %s(self):\n return %s' % (parameter_name, new_return)
code = compile(source, file_name, 'exec')`
class SubMyClass(MyClass):
eval(code)
obj.__class__ = SubMyClass
patch_property('func', [6,7,8])
This works, however it changes type(obj)
, which messes up some other stuff. Doing the following does not:
cls = type(obj)
new_cls = type(cls.__name__, (cls,), {})
obj.__class__ = new_cls
However, I can't figure out how to properly get the eval(code)
from above in the new_cls. Any ideas on how to solve this?
I also tried monkeypatching the property:
def patch_fun(code):
def patched_fun(self):
eval(code)
return patched_fun
patched_fun = patch_fun(code)
setattr(cls, name, property(patched_fun))
or the bound method:
patched_fun = patch_fun(code).__get__(obj, type(obj))
setattr(cls, name, property(patched_fun))
(I couldn't figure it out from these: Dynamically adding a property to a class , Dynamically adding @property in python, Monkey Patching an attribute within a class, Monkey patching a @property , Python: changing methods and attributes at runtime