python中双下划线的作用
(1)所有以双下划线开头的成员是私有的
(2)python对于私有变量是会进行扎压(mangling)的,扎压规则是
原始定义:
class A():
    __function():
          print '__function is private! '
扎压之后:
class A():
    _A__function():
          print '__function is private!'

同时,在class A中对于以前__function()的调用会被自动替换成对于_A__function()的调用。

/**如果对于上述规则不理解,请查看下面的内容(转载过来的)**/

引子

我热情地邀请大家猜测下面这段程序的输出:
class A(object):
       def __init__(self):
              self.__private()     #如果该行代码改成self._private()
              self.public()   
       def __private(self):  #def _private(self):
              print 'A.__private()' #print 'A._private()'
       def public(self):
              print 'A.public()'
class B(A):
       def __private(self):  #def _private(self):————————b=B()的正确答案是:B._private()
              print 'B.__private()' #print 'B._private()'                 B.public()
       def public(self):
              print 'B.public()
b = B()
初探
正确的答案是:
A.__private()                    #因为调用A的构造函数时,加双下划线的是私有变量只有类对象自己能访问,连子类对象也不能访问到这个数据.
B.public()                         #调用A的构造函数时,子类B的public方法覆盖父类A的Public方法。
 
如果您已经猜对了,那么可以不看我这篇博文了。如果你没有猜对或者心里有所疑问,那我的这篇博文正是为您所准备的。
一切由为什么会输出“A.__private()”开始。但要讲清楚为什么,我们就有必要了解一下Python的命名机制。
据 Python manual,变量名(标识符)是Python的一种原子元素。当变量名被绑定到一个对象的时候,变量名就指代这个对象,就像人类社会一样,不是吗?当变量名出现在代码块中,那它就是本地变量;当变量名出现在模块中,它就是全局变量。模块相信大家都有很好的理解,但代码块可能让人费解些。在这里解释一下:
代码块就是可作为可执行单元的一段Python程序文本;模块、函数体和类定义都是代码块。不仅如此,每一个交互脚本命令也是一个代码块;一个脚本文件也是一个代码块;一个命令行脚本也是一个代码块。
接下来谈谈变量的可见性,我们引入一个范围的概念。范围就是变量名在代码块的可见性。 如果一个代码块里定义本地变量,那范围就包括这个代码块。如果变量定义在一个功能代码块里,那范围就扩展到这个功能块里的任一代码块,除非其中定义了同名 的另一变量。但定义在类中的变量的范围被限定在类代码块,而不会扩展到方法代码块中。
迷踪
据上节的理论,我们可以把代码分为三个代码块:类A的定义、类B的定义和变量b的定义。根据类定义,我们知道代码给类A定义了三个成员变量(Python的函数也是对象,所以成员方法称为成员变量也行得通。);类B定义了两个成员变量。这可以通过以下代码验证:
>>> print '\n'.join(dir(A))
_A__private
__init__
public
>>> print '\n'.join(dir(B))
_A__private
_B__private
__init__
public
咦,为什么类A有个名为_A__private的 Attribute 呢?而且__private消失了!这就要谈谈Python的私有变量轧压了。
探究
懂Python的朋友都知道Python把以两个或以上下划线字符开头且没有以两个或以上下划线结尾的变量当作私有变量。私有变量会在代码生成之前被转换为长格式(变为公有)。转换机制是这样的:在变量前端插入类名,再在前端加入一个下划线字符。这就是所谓的私有变量轧压(Private name mangling)。如类A里的__private标识符将被转换为_A__private,这就是上一节出现_A__private和__private消失的原因了。
再讲两点题外话:
一是因为轧压会使标识符变长,当超过255的时候,Python会切断,要注意因此引起的命名冲突。
二是当类名全部以下划线命名的时候,Python就不再执行轧压。如:
>>> class ____(object):
       def __init__(self):
              self.__method()
       def __method(self):
              print '____.__method()'
>>> print '\n'.join(dir(____))
__class__
__delattr__
__dict__
__doc__
__getattribute__
__hash__
__init__
__method              # 没被轧压
__module__
__new__
__reduce__
__reduce_ex__
__repr__
__setattr__
__str__
__weakref__
>>> obj = ____()
____.__method()
>>> obj.__method()      # 可以外部调用
____.__method()
现在我们回过头来看看为什么会输出“A.__private()”吧!
真相
相信现在聪明的读者已经猜到答案了吧?如果你还没有想到,我给你个提示:真相跟C语言里的宏预处理差不多。
因为类A定义了一个私有成员函数(变量),所以在代码生成之前先执行私有变量轧压(注意到上一节标红的那行字没有?)。轧压之后,类A的代码就变成这样了:
class A(object):
       def __init__(self):
              self._A__private()          # 这行变了
              self.public()
       def _A__private(self):           # 这行也变了
              print 'A.__private()'
       def public(self):
              print 'A.public()'
是不是有点像C语言里的宏展开啊?
因为在类B定义的时候没有覆盖__init__方法,所以调用的仍然是A.__init__,即执行了self._A__private(),自然输出“A.__private()”了。
下面的两段代码可以增加说服力,增进理解:
>>> class C(A):
       def __init__(self):          #重写 __init__,不再调用 self._A__private
              self.__private()       # 这里绑定的是 _C_private
              self.public()
       def __private(self):
              print 'C.__private()'
       def public(self):
              print 'C.public()'
>>> c = C()
C.__private()
C.public()
############################
>>> class A(object):
       def __init__(self):
              self._A__private()   # 调用一个没有定义的函数, Python会把它给我的 
              self.public()
       def __private(self):
              print 'A.__private()'
       def public(self):
              print 'A.public()'
>>>a = A()
A.__private()
A.public()

python——双下划线与python命名机制的更多相关文章

  1. php 以单下划线或双下划线开头的命名

    有2个下划线的是魔术方法,如:__construct.__destruct等等.有1个下划线的一般是私有方法,如 _initialize. 小测试: public function _test(){ ...

  2. python 私有和保护成员变量如何实现?—— "单下划线 " 开始的成员变量叫做保护变量,意思是只有类实例和子类实例能访问到这些变量;" 双下划线 " 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据

    默认情况下,Python中的成员函数和成员变量都是公开的(public),在python中没有类似public,private等关键词来修饰成员函数和成员变量.在python中定义私有变量只需要在变量 ...

  3. python中_、__、__xx__(单下划线、双下划线等)的含义

    (1)_xxx "单下划线 " 开始的成员变量相当于私有变量,也叫做保护变量,意思是只有类实例和子类实例能访问到这些变量,需通过类提供的接口进行访问(可以定义有点像java中的ge ...

  4. python的下划线

    首先是单下划线开头,这个被常用于模块中,在一个模块中以单下划线开头的变量和函数被默认当作内部函数,如果使用 from a_module import * 导入时,这部分变量和函数不会被导入.不过值得注 ...

  5. [Python Basics]下划线变量

    夜暗归云绕柁牙,江涵星影鹭眠沙. 行人怅望苏台柳,曾与吴王扫落花. 我平时很常见到的带有下划线的python变量有两种: 前后双下划线,我之前的理解是python程序中的类似meta data的信息, ...

  6. Python中单下划线与双下划线用法总结

    看mentor的脚本时,遇到self._item.callspec.getparam('')语句,理解起来比较困难,找到一篇文章,记录的比较详细,特别记录一下,以备复习. 附链接地址:http://w ...

  7. python 里面的单下划线与双下划线的区别

    python 里面的单下划线与双下划线的区别 Python 用下划线作为变量前缀和后缀指定特殊变量. _xxx 不能用'from moduleimport *'导入 __xxx__ 系统定义名字 __ ...

  8. python中那些双下划线开头得函数和变量--转载

    Python中下划线---完全解读     Python 用下划线作为变量前缀和后缀指定特殊变量 _xxx 不能用'from module import *'导入 __xxx__ 系统定义名字 __x ...

  9. python python中那些双下划线开头的那些函数都是干啥用用的

    1.写在前面 今天遇到了__slots__,,所以我就想了解下python中那些双下划线开头的那些函数都是干啥用用的,翻到了下面这篇博客,看着很全面,我只了解其中的一部分,还不敢乱下定义. 其实如果足 ...

随机推荐

  1. GPS经纬度的表示方法及换算

    想要认识GPS中的经纬度,就必须先了解GPS,知道经纬度的来源: 1. GPS系统组成 GPS是 Gloabal Positioning System 的简称,意为全球定位系统,主要由地面的控制站.天 ...

  2. Andriod布局

    布局[ViewGroup]   像素单位的变化:是用dip,而不是px,主要用于宽高的设置 在Android中支持的描述大小区域的类型有以下几种. px(pixels)——像素:不同的设备显示效果相同 ...

  3. 利用WM_COPYDATA进行进程间通信

    发信消息 void CControlDlg::OnBnClickedButtonSend() { // TODO: 在此添加控件通知处理程序代码 CString strWindowTitle = _T ...

  4. Selenium2+python自动化19-单选框和复选框(radiobox、checkbox)【转载】

    本篇主要介绍单选框和复选框的操作 一.认识单选框和复选框 1.先认清楚单选框和复选框长什么样 2.各位小伙伴看清楚哦,上面的单选框是圆的:下图复选框是方的,这个是业界的标准,要是开发小伙伴把图标弄错了 ...

  5. centos7安装gitlab与gitlab的汉化

    Gitlab概述 GitLab是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目.  GitLab拥有与Github ...

  6. es6记录

    3.5? 一.const 1.冻结对象 const foo = Object.freeze({}); // 常规模式时,下面一行不起作用: // 严格模式时,该行会报错 foo.prop = ; 2. ...

  7. 几何【P2313】 [HNOI2005]汤姆的游戏

    顾z 你没有发现两个字里的blog都不一样嘛 qwq 题目描述--->p2313 [HNOI]汤姆的游戏 分析 说不上是分析. 数据范围给出来,这题明显暴力啊emmm. 个人认为的坑点. 这题不 ...

  8. x-pack-crack

    破解x-pack-----------1. 编辑文件:LicenseVerifier.javapackage org.elasticsearch.license;import java.nio.*;i ...

  9. TestList汇总

    [基本类型] 类的构造方法调用问题 重载复写的区别 Final finally finalized 的区别 定义final变量是否需要初始化 forward和redirect的区别 equals方法和 ...

  10. APIO2018练习赛伪题解

    传送门:https://pcms.university.innopolis.ru/statements/org/apio/2018/practice/statements.pdf 主要就在于后面三道构 ...