关于注入方法中的Access私有变量:访问注入方法中的私有变量 – python

Access private variables in injected method - python

问题到此为止

我要做的是:

  • 将属性注入到已创建的对象并设置它而不是变量(成功)
  • 向创建的对象注入方法(我们称之为方法),对象以前没有这样的方法(成功)
  • 使用self从属性调用public另一个方法(成功)
  • 使用self从属性调用方法(成功)
  • 使用self从方法获取私有类变量(失败)
  • 下面是一些代码:

    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"成员的名称管理严格在类定义中完成。要实现所需的目的,即将self.__hidden转换为self._Simulation_hidden,只需在适当命名的类中定义它。

    例如:

    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

    现在,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

    扩展

    这依赖于我们对要添加方法的类的名称进行硬编码(Simulation)。为了避免这种情况,我们可以使用exec

    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

    不幸的是,我们要添加的函数必须定义为文本,它不能是一些已经定义的任意函数对象。(这可以通过使用inspect找到其源代码,然后使用exec在类节中重新编译该源代码(以及明智地选择globals来解决)。