我已经读过各种各样的" 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']
您可以对实例 thing 做什么来获取对原始字符串的读取权限(忽略我的弱加密)或写入对它的访问权限?
我本周向我的学生讲授Python课程,我试图理解为什么,给定闭包,JavaScript和& amp; amp; amp; Perl不会为Python工作。
谢谢。
答案 0 :(得分:4)
如果你只是想访问原文,那就不那么难了,因为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
而且,嘿!我们得到了原始价值。
修改价值更难 - 但并非不可能 - (见here)。针对此设置进行了修改:
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()
答案 1 :(得分:3)
您通常不会这样做,但您可以使用模块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'
给定闭包中的一个函数,您可以访问闭包的变量。我还没有找到修改变量的方法。
因此,如果你愿意付出一些努力,这并非不可能。为什么你会在我不知道的正常编程过程中这样做。