p y t h o n 中 单 下 划 线 和 双 下 划 线 的 意 义 python中单下划线和双下划线的意义 python中单下划线和双下划线的意义


前导单下划线

_major:一种约定,用来指定变量私有。具有前导下划线的类中的名称只是向其他程序员指示该属性或方法是私有的,但是,名称本身并没有什么特别之处.

具有前导下划线的类中的名称只是向其他程序员指示该属性或方法是私有的。这是一种默认的惯例。不能用from module import *导入,其他方面和公有一样访问。

这是一种指示内部使用的惯例约定。但是,Python并不会阻止任何人去访问带前导单下划线的属性,它仍可以被外界获取。这个惯例约定同样适用于模块,函数的命名。


前导双下划线

__major:这个有真正的意义:解析器用_classname__major来代替这个名字,以区别和其他类相同的命名。

__double_leading_underscore:在命名一个类属性时,调用名称修改,比如:在类Major中,类属性__boo会变为_Major__boo

前导双下划线的属性或方法名会改变成其它形式。调用名称修改的目的就是为了继承,为类提供一种简单的方法来定义“私有”实例变量和方法,而不必担心派生类定义的实例变量,或者通过类外部的代码来修改实例变量。


双向双下划线

__init__:一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突。

__double_leading_and_trailing_underscore__:常见于Python内置的“魔术”对象或属性,例如,__init__,__import__或__file__,为了区别于用户自定义的__double_leading_underscore。它们会被Python系统调用的,不用用户自己调用。

双向双下划线

一般用于Python自己内置的方法属性。


示例

>>> class MyClass():
...     def __init__(self):
...         self.__superprivate = "Hello"
...         self._semiprivate = ", world!"
...     def __add__(self, new_str):
...         return " ".join([self.__superprivate, new_str])
...
>>> 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!'}
>>> print(mc + "xxx")
Hello xxx

在上面这个例子中,虽然我们认为_semiprivate是私有的,但我们还是可以直接调用,Python并没有真正的支持私有化,前导单下划线的私有性只是一种编程规范

但是,我们无法直接使用mc.__superprivate,因为类属性__superprivate已经更名为_MyClass__superprivate

这样的好处是,假象一下,你有一个子类MySubClass,它的私有属性就会重命名为_MySubClass__superprivate,而父类的私有属性就不会被覆盖。去修改子类的私有属性而不会去影响到父类。

__add__是魔法方法,它是有Python系统自己调用。上例中,我们没有显式地调用它,而是使用运算符mc + "xxx",而其背后,Python就隐式调用了__add__

Tips: 如果你定义的变量与某个保留关键字冲突,可以使用后置单下划线。