对此有一个范围。更多的隐私需要更多的工作,但更难绕过。 “真正私密”没有明确的界限。
前导双下划线是最不私密的选项。在属性上添加前导双下划线很容易,但也很容易通过手动名称修改绕过。
代码和绕过:
class Private1:
def __init__(self, data):
self.__data = data
def get_data(self):
return self.__data
x = Private1(1)
# Direct access fails...
x.__data = 2
# but you can do the name mangling manually.
x._Private1__data = 2
接下来是闭包变量或隐藏槽之类的东西。您无法通过名称修改来访问它们,但您仍然可以手动访问闭包单元或找出插槽吸气剂的位置。
闭包变量示例,带旁路:
class Private2:
def __init__(self, data):
def get_data():
return data
self.get_data = get_data
x = Private2(1)
# It's not immediately obvious how you'd even try to access the data variable directly,
# but you can:
x.get_data.__closure__[0].cell_contents = 2
隐藏槽示例,带旁路:
class Private3:
__slots__ = ('data',)
def __init__(self, data):
_hidden_slot.__set__(self, data)
def get_data(self):
return _hidden_slot.__get__(self, type(self))
_hidden_slot = Private3.data
del Private3.data
x = Private3(1)
# Direct access fails...
x.data = 2
# but you can directly access the slot getter the same way the actual class did:
_hidden_slot.__set__(x, 2)
之后的下一步将是 C 扩展。手动编写一个 C 扩展需要做很多工作,我不打算再举一个例子了(但这里有一个 tutorial link 和 Cython 使它更容易),但在 C 中实现的类型不会默认情况下在 Python 级别公开其内部数据。如果该类型没有特别努力提供访问权限,那么访问数据的唯一方法是使用更多 C,或者使用 ctypes 或 gc.get_referents 之类的东西(如果隐藏数据是 GC 公开的 Python 引用) . (正确使用gc.get_referents也可以绕过上述所有其他保护。)
之后的下一步是将数据保存在您自己的私有服务器上,并且只允许客户端通过 Internet API 访问它。这比任何private 关键字都更加私密,绕过它需要诸如漏洞利用、传票或身体暴力之类的东西。