精华内容
下载资源
问答
  • python双下划线的作用(1)所有以双下划线开头的成员是私有的(2)python对于私有变量是会进行扎压(mangling)的,扎压规则是原始定义:class A():__function():print '__function is private! '扎压之后:class A():_A...

    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()

    展开全文
  • 该代码片段来自Django源码(django/forms/...双下划线开头之前很多人跟我说Python双下划线开头表示私有,我在很多地方也见到这样的说法。这样理解可能也不能说错,但这不是Python设计双下划线开头的初衷和目的,...

    该代码片段来自Django源码(django/forms/forms.py)。这段代码的设计就是errors属性是对外API的一部分,如果你想获取错误详情,应该访问errors属性,而不是(也不应该)访问_get_errors方法。

    双下划线开头

    之前很多人跟我说Python中双下划线开头表示私有,我在很多地方也见到这样的说法。这样理解可能也不能说错,但这不是Python设计双下划线开头的初衷和目的,Python设计此的真正目的仅仅是为了避免子类覆盖父类的方法。

    我们看个例子:

    执行结果:

    这里有两个点需要注意:

    A类中我们定义了__method()、method_x和method()三个方法;然后我们重新定义一个类B,继承自A,并且在B类中覆写(override)了其父类的__method()和method_x方法,但是从输出结果看,B对象调用method()方法时调用了其父类A的__method()方法和自己的method_x()方法。也就是说,__method()覆写没有生效,而method_x()覆写生效了。而这也正是Python设计双下划线开头的唯一目的。

    前面我们就说了,Python中不存在真正意义上的私有变量。对于双下划线开头的方法和属性虽然我们不能直接引用,那是因为Python默认在其前面加了前缀_类名,所以就像situation 2下面的代码,虽然我们不能用a直接访问__method(),但却可以加上前缀去访问,即_A__method()。

    开头结尾双下划线

    一般来说像__this__这种开头结尾都加双下划线的方法表示这是Python自己调用的,你不要调用。比如我们可以调用len()函数来求长度,其实它后台是调用了__len__()方法。一般我们应该使用len,而不是直接使用__len__():

    我们一般称__len__()这种方法为magic methods,一些操作符后台调用的也是也是这些magic methods,比如+后台调用的是__add__,-调用的是__sub__,所以这种机制使得我们可以在自己的类中覆写操作符(见后面例子)。另外,有的时候这种开头结尾双下划线方法仅仅是某些特殊场景的回调函数,比如__init__()会在对象的初始化时调用,__new__()会在构建一个实例的时候调用等等。下面我们看两个例子:

    在上面这个例子中,我们覆写了+和-操作符,将他们的功能交换了。再看个例子:

    这个例子中,因为我们实现了__len__(),所以Room对象也可以使用len函数了。

    所有此类的方法都在这里有说明:documentation.

    结论使用单下划线(_one_underline)开头表示方法不是API的一部分,不要直接访问(虽然语法上访问也没有什么问题)。

    使用双下划线开头(__two_underlines)开头表示子类不能覆写该方法。除非你真的知道你在干什么,否则不要使用这种方式。

    当你想让自己定义的对象也可以像Python内置的对象一样使用Python内置的一些函数或操作符(比如len、add、+、-、==等)时,你可以定义该类方法。

    当然还有些属性只在末尾加了但下划线,这仅仅是为了避免我们起的一些名字和Python保留关键字冲突,没有特殊含义。

    展开全文
  • Python下划线作为变量前缀和后缀指定特殊变量。_xxx 不能用'from module import *' 导入__xxx__ 系统定义名字__xxx 类中的私有变量名在 Python的官方推荐的代码样式中,还有一种单下划线结尾的样式,这在解析时并...

    Python 用下划线作为变量前缀和后缀指定特殊变量。

    _xxx 不能用'from module import *' 导入

    __xxx__ 系统定义名字

    __xxx 类中的私有变量名

    在 Python 的官方推荐的代码样式中,还有一种单下划线结尾的样式,这在解析时并没有特别的含义,

    但通常用于和 Python关键词区分开来,比如如果我们需要一个变量叫做 class,但 class 是 Python

    的关键词,就可以以单下划线结尾写作 class_。

    核心风格:避免用下划线作为变量名的开始。

    因为下划线对解释器有特殊的意义,而且是内建标识符所使用的符号,我们建议程序员避免用下

    划线作为变量名的开始。一般来讲,变量名_xxx被看作是“私有 的”,在模块或类外不可以使用。

    当变量是私有的时候,用_xxx 来表示变量是很好的习惯。因为变量名__xxx__对Python 来说

    有特殊含义,对于普通的变量应当避免这种命名风格。

    "单下划线" 开始的成员变量叫做保护变量,意思是只有类对象和子类对象自己能访问到这些变量;

    "双下划线" 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数

    据。

    以单下划线开头(_foo)的代表不能直接访问的类属性,需通过类提供的接口进行访问,不

    能用“from xxx import *”而导入;以双下划线开头的(__foo)代表类的私有成员;以双下划

    线开头和结尾的(__foo__)代表python里特殊方法专用的标识,如 __init__()代表类的构

    造函数。

    结论:

    1、_xxx 不能用于’from module import *’ 以单下划线开头的表示的是protected类型的变量。

    即保护类型只能允许其本身与子类进行访问。

    2、__xxx 双下划线的表示的是私有类型的变量。只能是允许这个类本身进行访问了。连子类也

    不可以

    3、__xxx___ 定义的是特列方法。像__init__之类的

    展开全文
  • 探究 懂Python的朋友都知道Python把以两个或以上下划线字符开头且没有以两个或以上下划线结尾的变量当作私有变量。 私有变量会在代码生成之前被转换为长格式(变为公有)。转换机制是这样的:在变量前端插入类名,再...

    引子

    我热情地邀请大家猜测下面这段程序的输出:

    class A(object):

    def __init__(self):

    self.__private()

    self.public()

    def __private(self):

    print 'A.__private()'

    def public(self):

    print 'A.public()'

    class B(A):

    def __private(self):

    print 'B.__private()'

    def public(self):

    print 'B.public()'

    b = B()

    初探

    正确的答案是:

    A.__private()

    B.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()

    展开全文
  • add by zhj:今天在学习SimpleHTTPServer的源代码时,看到了Python标准库SocketServer模块中有个BaseServer类,该类的__init__方法定义如下def __init__(self, server_address, RequestHandlerClass):"""Constructor...
  • 自己一般在写类的时候,很少用__的私有变量,很多进阶书籍也提示,少用__下划线的私有变量,避免引起不必要的麻烦,可以用_单下划线代替。首先说明一个核心思想,Python在处理__的变量名的时候,会通过_类名__属性名...
  • python双下划线含义、MethodType把函数变为方法以及类继承
  • _ _new _ _(cls[,...]) _ _ new _ _()才是一个对象实例化时调用的第一个方法,它和其他的双下划线包围的方法不同,它的第一个参数不是sel而是这个类(cls),而其他的参数会直接传递给 _ _ init() _ _ 方法的。...
  • http://wiki.intra.xiaojukeji.com/pages/viewpage.action?pageId=205555865
  • 我对这种行为有点困惑(使用python 3.2):class Bar:passbar = Bar()bar.__cache = Noneprint(vars(bar)) # {'__cache': None}class Foo:def __init__(self):self.__cache = Nonefoo = Foo()print(vars(foo)) # {'_F....
  • python双下划线函数

    2018-09-26 10:41:00
    def func(f): def inner(*args, **kwargs): print('1') ret = f(*args, **kwargs) print('2') return ret return inner @func def asd(bool): print('%s'...
  • 1.python 中__name__ = '__main__' 的作用如果我们是直接执行某个.py文件的时候,该文件中那么”__name__ == '__main__'“是True,但是我们如果从另外一个.py文件通过import导入该文件的时候,这时__name__的值就是...
  • python 双下划线命名

    2016-03-12 19:47:37
    Python的朋友都知道Python把以两个或以上下划线字符开头且没有以两个或以上下划线结尾的变量当作私有变量。私有变量会在代码生成之前被转换为长格式(变为公有)。转换机制是这样的:在变量前端插入类名,再在前端...
  • Python下一切皆对象,每个对象都有多个属性(attribute),Python对属性有一套统一的管理方案。 __dict__与dir()的区别: dir()是一个函数,返回的是list; __dict__是一个字典,键为属性名,值为属性值; dir...
  • 在 前导双下划线(没有尾随的双下划线)表示不同的含义。在方法名或其他属性中,这意味着名称应该是“混乱的”,这样子类或超类在打算定义和使用自己的私有名称时更难意外地调用或重写它。在通常,这是一个很好的匹配...
  • (1)_xxx"单下划线" 开始的成员变量相当于私有变量,也叫做保护变量,意思是只有类实例和子类实例能访问到这些...其实,Python并没有真正的私有化支持,用下划线得到的是伪私有,也就是说如果你强行要用也是可以的...
  • 自己使用双下划线方法制作扑克牌 import json from collections import namedtuple # 调用namedtuple()生成Card类 Card = namedtuple( " Card " , [ " rank " , " suit " ]) # rank 牌面大小 suit 牌面花色 ...
  • 背景看python源码时,经常会看到一些类方法、变量等以单下划线开头、以双下划线开头、以双下划线开头且以双下划线结尾,看来看去经常晕头转向的,所以专门学习了下。主要内容涉及以下内容。 说明:下面的内容均会在...
  • 概述本文主要介绍一些关于类变量、实例变量的一些基本内容类、实例 类:class,与面向对象中的类的概念相同 实例:类的一个对象,与面相对象中的对象/实例的概念相同 类变量、实例变量 类变量:类本身所拥有的变量...
  • Python下划线作为变量前缀和后缀指定特殊变量。_xxx 不能用'from moduleimport *'导入__xxx__ 系统定义名字(类似于java 的default修饰)__xxx 类中的私有变量名(类似于java的private修饰)核心风格:避免用...
  • python 单下划线跟双下划线使用

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,263
精华内容 1,305
关键字:

python双下划线

python 订阅