重新访问Python私有实例数据

cdl*_*ane 5 javascript python perl closures private

我已经阅读了各种"Python实例中没有真正的私有数据"帖子,但我们都知道在Perl和JavaScript中使用闭包来有效地实现私有数据.那么为什么不在Python?例如:

import codecs

class Secret:
    def __private():
        secret_data = None

        def __init__(self, string):
            nonlocal secret_data
            if secret_data is None:
                secret_data = string

        def getSecret(self):
            return codecs.encode(secret_data, 'rot_13')

        return __init__, getSecret

    __init__, getSecret = __private()
Run Code Online (Sandbox Code Playgroud)

现在我们做:

>>> thing = Secret("gibberish")
>>> thing.getSecret()
'tvoorevfu'
>>> dir(thing)
['_Secret__private', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'getSecret']
Run Code Online (Sandbox Code Playgroud)

您可以对实例事项什么来获取原始字符串的读取权限(忽略我的弱加密)或写入访问权限?

我本周正在向我的学生讲授Python课程,我试图理解为什么,给定闭包,JavaScript和Perl的技术不适用于Python.

谢谢.

ig0*_*774 5

如果你只是想访问原始的,也没有那么难,因为Python函数实现了一个相当彻底的检查api。您可以使用以下内容访问原始机密:

thing = Secret("gibberish")
# __init__ doesn't need to be used here; anything defined within the closure will do
thing.__init__.__func__.__closure__[0].cell_contents
Run Code Online (Sandbox Code Playgroud)

而且,嘿!我们得到原始值。

更难---但并非不可能---修改该值(请参阅此处)。为此设置修改:

import ctypes
...

thing = Secret("gibberish")
cell = ctypes.py_object(thing.__init__.__func__.__closure__[0])
new_value = ctypes.py_object('whatever')
ctypes.pythonapi.PyCell_Set(cell, new_value)

thing.getSecret()
Run Code Online (Sandbox Code Playgroud)