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
compile()inside your code seems like a massive securiry breach. In previous posts there are attempts to use setatrr and a lambda function, which feel more reasonable.