Access private variables in injected method - python
问题到此为止
我要做的是:
下面是一些代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | from types import MethodType def add_property(instance, name, method): cls = type(instance) cls = type(cls.__name__, (cls,), {}) cls.__perinstance = True instance.__class__ = cls setattr(cls, name, property(method)) def add_variable(instance, name, init_value = 0 ): setattr(type(instance), name, init_value) class Simulation: def __init__(self): self.finished = False self.__hidden = -10 def someloop(self): while not self.finished: self.__private_method() def __private_method(self): pass def public_method(self): pass def mocked_method(self): print(type(self)) print(self.__dict__) print(self.__hidden) def finished(self): print("Execute finished",type(self)) self.public_method() self.mocked_update() return True simulation = Simulation() add_property(simulation,"finished", finished) add_variable(simulation,"count_finished", 0) simulation.mocked_update = MethodType(mocked_method, simulation) simulation.someloop() |
产生了什么代码(那些印刷品):
1 2 3 4 5 | Execute finished '<class '__main__.Simulation'> <class '__main__.Simulation'> {'finished': False, '_Simulation__hidden': -10, 'mocked_update': <bound method mocked_method of <__main__.Simulation object at 0x030D2F10>>} (...) AttributeError: 'Simulation' object has no attribute '__hidden' |
号
正如您所看到的,self应该是什么(模拟类),它被正确地注入,但它不起作用。如果你想知道:
1 | print(self._Simulation__hidden) |
很明显,在模拟的更新中工作。
因此我的问题是:是否有机会使用self访问这个变量?
动机
因为评论部分有一个问题:
这没有任何实际意义,只是一个实验。
"private"成员的名称管理严格在类定义中完成。要实现所需的目的,即将
例如:
1 2 3 4 5 6 7 8 9 | def make_mocked_method(): class Simulation: # this is your code, but now its inside a class stanza so '__' will be mangled def mocked_method(self): print(type(self)) print(self.__dict__) print(self.__hidden) return Simulation.mocked_method |
现在,
1 2 | simulation.mocked_update = MethodType(make_mocked_method(), simulation) simulation.someloop() |
号
给予:
1 2 3 | <class '__main__.Simulation'> {'finished': False, 'mocked_update': <bound method make_mocked_method.<locals>.Simulation.mocked_method of <__main__.Simulation object at 0x101c00a58>>, '_Simulation__hidden': -10} -10 |
扩展
这依赖于我们对要添加方法的类的名称进行硬编码(
1 2 3 4 5 6 7 8 9 10 | def make_mocked_method(cls): txt ="""class {}: def mocked_method(self): print(type(self)) print(self.__dict__) print(self.__hidden) """.format(cls.__name__) ns = {} exec(txt, ns) return ns[cls.__name__].mocked_method |
。
不幸的是,我们要添加的函数必须定义为文本,它不能是一些已经定义的任意函数对象。(这可以通过使用