Python中的私有成员
如何在Python中使方法和数据成员私有?或者Python不支持私有成员 如果Python函数的名称, 类方法,或属性以 (但不是以)两个结尾 强调,这是私人的一切 其他的都是公开的。Python没有概念 受保护类方法的类型(可访问) 只有他们自己的阶级和后代 课程)。类方法是 私人(仅在其自己的 类)或公共(可从 任何地方) “私有”实例变量 只能从内部访问 一个对象,在Python中不存在。 然而,有一个惯例是 后面是大多数Python代码:名称 以下划线作为前缀(例如。 _垃圾邮件)应被视为API的非公开部分(无论是否 是函数、方法还是数据 成员)。这应该被视为一种挑战 实施细节和可能的风险 未经通知而更改 因为有一个有效的用例 类私有成员(即避免 名称与名称的冲突 由子类定义),有 对这一机制的支持有限, 叫“弄脏”这个名字。任何标识符 垃圾邮件的形式(至少两种) 前导下划线,最多一个 尾随下划线)以文本形式显示 替换为Python中的私有成员,python,class,oop,member-variables,Python,Class,Oop,Member Variables,如何在Python中使方法和数据成员私有?或者Python不支持私有成员 如果Python函数的名称, 类方法,或属性以 (但不是以)两个结尾 强调,这是私人的一切 其他的都是公开的。Python没有概念 受保护类方法的类型(可访问) 只有他们自己的阶级和后代 课程)。类方法是 私人(仅在其自己的 类)或公共(可从 任何地方) “私有”实例变量 只能从内部访问 一个对象,在Python中不存在。 然而,有一个惯例是 后面是大多数Python代码:名称 以下划线作为前缀(例如。 _垃圾邮件)应
\u classname\u垃圾邮件
,其中
classname是当前的类名
去掉前导下划线。
这种弄脏是不加考虑的
到的句法位置
标识符,只要它出现
在类的定义中
所以
将输出:
['_Test__private_symbol',
'__doc__',
'__module__',
'normal_symbol']
\uuuu private\u symbol
应视为专用方法,但仍可通过\u Test\uu private\u symbol
访问。其他答案提供了技术细节。我想强调Python与C++/Java等语言(基于您的问题,我认为您熟悉这些语言)在哲学上的差异
Python(以及Perl)的一般态度是,属性的“隐私”是程序员的请求,而不是编译器/解释器的铁丝网。这一想法在中得到了很好的总结,通常被称为“我们都是同意的成年人”,因为它“假设”程序员有足够的责任,不干涉内部事务。前导下划线用作礼貌信息,表示该属性是内部属性
另一方面,如果您确实希望访问某些应用程序的内部构件(一个显著的例子是像pydoc这样的文档生成器),您可以自由地这样做。作为一名程序员,你有责任知道自己在做什么并正确地做,而不是用语言强迫你按自己的方式做。Python中没有任何其他访问保护机制的
private
。中有一个约定,用于向类的用户指示他们不应访问某些属性
- _单前导下划线:弱“内部使用”指示器。例如,M import*中的
不会导入名称以下划线开头的对象
- 单尾随下划线:按惯例使用,以避免与Python关键字冲突,例如
Tkinter.Toplevel(master,class='ClassName')
- __双下划线:在命名类属性时,调用名称混乱(在类FooBar中,\uuuboo变成了\ufoobar\uboo;见下文)
你可以这样做: >>>p._Person__priva I am Private >>>p、 私人 我是私人的 哇,事实上,如果python得到任何以双下划线开头的变量,则会通过在开头添加一个下划线和类名来“转换”: 注意:如果您不希望更改此名称,但仍希望发送信号让其他对象远离,则可以使用带有初始下划线的单个初始下划线名称。不使用带星号的导入(从模块导入*)导入名称。
例如: #test.py def hello(): print "hello" def _hello(): print "Hello private" #---------------------- #test.py def hello(): 打印“你好” def_hello(): 打印“Hello private” #---------------------- #test2.py 从测试导入* 打印hello() 打印_hello() 输出--> 你好 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 NameError:未定义名称“\u hello” 现在,如果我们手动打电话给你好 #test2.py from test import _hello , hello print hello() print _hello() #test2.py 从测试导入(hello,hello) 打印hello() 打印_hello() 输出--> 你好 你好,二等兵 最后:Python实际上没有同等的隐私支持,尽管是单一的
如果您想在Python中使方法或数据成员私有,双首下划线在某种程度上为您提供了两个级别的隐私, 使用_usetattr__
class Number:
def __init__(self,value):
self.my_private = value
def __setattr__(self, my_private, value):
# the default behavior
# self.__dict__[my_private] = value
raise Exception("can't access private member-my_private")
def main():
n = Number(2)
print(n.my_private)
if __name__ == '__main__':
main()
这可能会奏效:
import sys, functools
def private(member):
@functools.wraps(member)
def wrapper(*function_args):
myself = member.__name__
caller = sys._getframe(1).f_code.co_name
if (not caller in dir(function_args[0]) and not caller is myself):
raise Exception("%s called by %s is private"%(myself,caller))
return member(*function_args)
return wrapper
class test:
def public_method(self):
print('public method called')
@private
def private_method(self):
print('private method called')
t = test()
t.public_method()
t.private_method()
这是一个l-o-n-g的答案,但我认为它触及了真正问题的根源——可见性的范围。坚持住,让我慢慢来 简单地导入一个模块不一定会让应用程序开发人员访问所有i #test2.py from test import _hello , hello print hello() print _hello() hello hello private
class Number:
def __init__(self,value):
self.my_private = value
def __setattr__(self, my_private, value):
# the default behavior
# self.__dict__[my_private] = value
raise Exception("can't access private member-my_private")
def main():
n = Number(2)
print(n.my_private)
if __name__ == '__main__':
main()
import sys, functools
def private(member):
@functools.wraps(member)
def wrapper(*function_args):
myself = member.__name__
caller = sys._getframe(1).f_code.co_name
if (not caller in dir(function_args[0]) and not caller is myself):
raise Exception("%s called by %s is private"%(myself,caller))
return member(*function_args)
return wrapper
class test:
def public_method(self):
print('public method called')
@private
def private_method(self):
print('private method called')
t = test()
t.public_method()
t.private_method()
class MyOBject(object):
def __init__(self):
self.__private_field = 10
my_object = MyOBject()
print(my_object.__private_field)