问题在最后
我想做的是:
现在,这里有一些代码:
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()
生成了什么代码(那些印刷品):
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'
正如你所看到的那样,自我应该是什么样的(模拟课程),它被正确地注入了,但它并没有起作用。 万一你想知道:
print(self._Simulation__hidden)
显然可以在mocked_update中使用。
因此我的问题:我是否有机会使用self访问此变量?
动机
由于评论部分有问题:
这不是任何真正的目的,只是一个实验。
答案 0 :(得分:3)
“私人”成员的名称严格在类定义中完成。要实现期望的目的,即将self.__hidden
翻译为self._Simulation_hidden
,您只需在适当命名的类中定义即可。
例如:
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
现在mocked_method
将正确访问所需的属性:
simulation.mocked_update = MethodType(make_mocked_method(), simulation)
simulation.someloop()
给出:
<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
这依赖于我们硬编码我们将方法添加到(Simulation
)的类的名称。为避免这种情况,我们可以使用exec
:
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
不幸的是,这里我们希望添加的函数必须定义为文本,它不能是一些已定义的任意函数对象。 (这可能通过使用inspect
查找其源代码然后使用exec
(并明智地选择globals
)在类节中重新编译该源来解决。