4 回答
![?](http://img1.sycdn.imooc.com/545847aa0001063202200220-100-100.jpg)
TA贡献1828条经验 获得超13个赞
单下划线
具有前导下划线的类中的名称只是向其他程序员指示该属性或方法是私有的。但是,名称本身并没有什么特别之处。
引用PEP-8:
_single_leading_underscore:弱“内部使用”指标。例如
from M import *
,不会导入名称以下划线开头的对象。
双下划线(名称管理)
从Python文档:
表单的任何标识符
__spam
(至少两个前导下划线,最多一个尾随下划线)在文本上被替换为_classname__spam
,其中classname
当前类名称被剥离了前导下划线。这种修改是在不考虑标识符的句法位置的情况下完成的,因此它可以用于定义类私有实例和类变量,方法,存储在全局变量中的变量,甚至存储在实例中的变量。在其他类的实例上对此类私有。
并在同一页面发出警告:
名称修改旨在为类提供一种简单的方法来定义“私有”实例变量和方法,而不必担心派生类定义的实例变量,或者通过类外部的代码来修改实例变量。请注意,修剪规则主要是为了避免事故; 确定的灵魂仍然可以访问或修改被视为私有的变量。
例
>>> class MyClass():
... def __init__(self):
... self.__superprivate = "Hello"
... self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}
![?](http://img1.sycdn.imooc.com/545865620001c45402760276-100-100.jpg)
TA贡献1853条经验 获得超18个赞
到目前为止优秀的答案,但一些花絮丢失。单个前导下划线并不仅仅是一个约定:如果使用from foobar import *
,并且模块foobar
未定义__all__
列表,则从模块导入的名称不包括具有前导下划线的名称。让我们说它主要是一种惯例,因为这个案例是一个非常模糊的角落;-)。
前导下划线约定不仅被广泛用于私有名称,而且被广泛用于C ++将其称为受保护的名称 - 例如,完全打算被子类覆盖的方法的名称(甚至是那些必须被覆盖的方法的名称)它们的基类raise NotImplementedError
! - )通常是单引导下划线名称,用于指示代码使用该类(或子类)的实例,这些方法不是直接调用的。
例如,要创建一个具有与FIFO不同的排队规则的线程安全队列,可以导入Queue,子类Queue.Queue,并覆盖这样的方法_get
和_put
; “客户端代码”从不调用那些(“hook”)方法,而是调用(“组织”)公共方法,例如put
和get
(这被称为模板方法设计模式 - 请参阅此处以获取基于视频的有趣演示文稿关于这个问题的我的谈话,增加了成绩单的概要)。
![?](http://img1.sycdn.imooc.com/545868b60001587202200220-100-100.jpg)
TA贡献1780条经验 获得超5个赞
__foo__
:这只是一种约定,是Python系统使用不会与用户名冲突的名称的一种方式。
_foo
:这只是一种约定,是程序员指示变量是私有的一种方式(无论在Python中是什么意思)。
__foo
:这具有实际意义:解释器将此名称替换_classname__foo
为确保名称不会与另一个类中的类似名称重叠的方式。
没有其他形式的下划线在Python世界中有意义。
这些约定中的类,变量,全局等没有区别。
![?](http://img1.sycdn.imooc.com/533e4c2300012ab002200220-100-100.jpg)
TA贡献1877条经验 获得超6个赞
._variable 是半私人的,只是为了惯例
.__variable经常被错误地认为是超级私有的,而它的实际意义只是为了防止意外访问[1]
.__variable__ 通常保留用于内置方法或变量
.__mangled如果你非常想要,你仍然可以访问变量。双重下划线只是将变量命名或重命名为类似的变量instance._className__mangled
例:
class Test(object):
def __init__(self):
self.__a = 'a'
self._b = 'b'
>>> t = Test()
>>> t._b
'b'
t._b是可访问的,因为它只是按惯例隐藏的
>>> t.__a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__a'
找不到t .__ a,因为它因名称错误而不再存在
>>> t._Test__a
'a'
通过访问instance._className__variable而不仅仅是双下划线名称,您可以访问隐藏值
添加回答
举报