Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/414.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 重新访问Python私有实例数据_Javascript_Python_Perl_Closures_Private - Fatal编程技术网

Javascript 重新访问Python私有实例数据

Javascript 重新访问Python私有实例数据,javascript,python,perl,closures,private,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 s

我读过各种“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()
现在我们做到了:

>>> 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']
您可以对实例做什么来获得对原始字符串的读访问权(忽略我的弱加密)或写访问权


本周我在教我的学生Python课程,我试图理解为什么在给定闭包的情况下,JavaScript和Perl技术不适用于Python。

您通常不会这样做,但可以使用模块
inspect
深入研究实例

>>> thing = Secret("gibberish")
>>> thing.getSecret()
'tvoorevfu'
>>> import inspect
>>> inspect.getclosurevars(thing.getSecret).nonlocals['secret_data']
'gibberish'
>>> inspect.getclosurevars(thing.__init__).nonlocals['secret_data']
'gibberish'
给定闭包中的一个函数,可以访问闭包的变量。我还没有找到修改变量的方法

所以,如果你愿意付出一些努力,这不是不可能的。我不知道为什么在正常的编程过程中会这样做。

如果您只想访问原始版本,这并不难,因为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
还有,嘿!我们得到原始值

修改该值比较困难,但并非不可能(请参阅)。已为此设置修改:

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()

谢谢@mhawke,我使用inspect模块强化了我的原始示例,但担心某些向导仍会使用它闯入。谢谢@ig0774,我已将init修复为不再是setter。您的链接似乎不适合于此讨论。我很高兴看到Python实现了它的目标,“有不止一种方法可以做到这一点。”座右铭——哦,等等,没关系。@cdlane:不知怎的,我想要的链接不是最终的链接。我已将其更新到正确的链接。基本上,您必须使用C API,但这仍然是可能的。@cdlane:请参阅我最近的编辑,该编辑演示了如何将单元格值设置为几乎任意的Python对象。如果您降到C级别,我不能通过将隐藏的数据移到C级别来进行计数,而只能让您降到C级别以下的机器代码来再次对我进行计数。您和mhawke都很容易让我相信,没有读保护,写保护可能是特定于实现的。也许Perl和JavaScript只是一个很好的内省包,它们也不能依靠闭包来隐藏数据。再次感谢。我想,根据这里使用的标准,即使是Java或C#也没有“真正”的私有数据,因为您可以使用反射或拖放到IL来覆盖任何内容,但这两种语言的标准环境都提供了控制访问级别的方法(通过代码签名等)。我认为更广泛的一点是,Python解释器不努力隐藏任何正在执行的代码,事实上,它不遗余力地公开了大量关于解释器正在做什么的信息。