精华内容
下载资源
问答
  • python下划线跟双下划线使用

    万次阅读 多人点赞 2017-09-18 19:39:54
    Python下划线作为变量前缀和后缀指定特殊变量/方法。 主要存在四种情形 object # public __object__ # special, python system use, user should not define like it __object # private (name mangling during...

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

    主要存在四种情形

    object # public
    __object__ # special, python system use, user should not define like it
    __object # private (name mangling during runtime)
     _object # obey python coding convention, consider it as private

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

         因为下划线对解释器有特殊的意义,而且是内建标识符所使用的符号,我们建议程序员避免用下划线作为变量名的开始。一般来讲,变量名_object被看作是“私有 的”,在模块或类外不可以使用,不能用'from moduleimport *'导入。当变量是私有的时候,用_object来表示变量是很好的习惯。因为变量名__object__对Python 来说有特殊含义,对于普通的变量应当避免这种命名风格。

         python有关private的描述,python中不存在protected的概念,要么是public要么就是private,但是python中的private不像C++, Java那样,它并不是真正意义上的private,通过name mangling(名称改编(目的就是以防子类意外重写基类的方法或者属性),即前面加上“单下划线”+类名,eg:_Class__object)机制就可以访问private了。

         "单下划线" 开始的成员变量叫做保护变量,意思是只有类对象和子类对象自己能访问到这些变量;"双下划线" 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。(如下列所示)
         以单下划线开头(_foo)的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用“from xxx import *”而导入;以双下划线开头的(__foo)代表类的私有成员;以双下划线开头和结尾的(__foo__)代表python里特殊方法专用的标识,如 __init__()代表类的构造函数。

     

    class Foo():
        def __init__():
            ...
        def public_method():
            print 'This is public method'
    
        def __fullprivate_method():
            print 'This is double underscore leading method'
    
        def _halfprivate_method():
            print 'This is one underscore leading method'


    实例化Foo的一个对象,

    f = Foo()
    f.public_method() # OK
    
    f.__fullprivate_method() # Error occur
    
    f._halfprivate_method() # OK
    
    f._Foo__fullprivate()_method() # OK

        从上面的例子可以看出,f._halfprivate_method()可以直接访问,确实是。不过根据python的约定,应该将其视作private,而不要在外部使用它们,(如果你非要使用也没辙),良好的编程习惯是不要在外部使用它。同时,根据Python docs的说明,_object和__object的作用域限制在本模块内。

    ==============================================================================
    理解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()

     

     

     

    展开全文
  • Python中存在一些特殊的方法,有些方法以双下划线 __ 开头和结尾,它们是Python的魔法函数,比如__init__()和__str__等等。不用要这种方式命名自己的变量或者函数。 class A: def __init__(self, text): self.text...

    双下划线开头和结尾

    Python中存在一些特殊的方法,有些方法以双下划线 __ 开头和结尾,它们是Python的魔法函数,比如__init__()__str__等等。不用要这种方式命名自己的变量或者函数。

    class A:
         def __init__(self, text):
             self.text = text
    
         def __str__(self):
            return self.text
    
    a = A("test")
    
    print(a)  # 输出test
    

    双下划线开头

    在前面加上__,表示它是私有成员,我们不能直接访问。比如 __xxx 如果要访问得通过 _class__xxx 的方式进行访问。虽然不能防止修改私有属性,但可以有效降低有意或者无意的修改。

    class A:
        def __init__(self):
            self.__name = "text"
    
    a = A()
    print(a.__name)  # 报错
    print(a._A__name)  # 输出text
    

    在这里插入图片描述
    从图中可以看到双下划线开头的变量,Python自动在前面加上了 _class的前缀,所以我们访问时也要加上相应的前缀才能正常访问

    单下划线开头

    _xxx:一种约定,用来指定变量私有。程序员用来指定私有变量的一种方式。不能用from module import *导入,其他方面和公有一样访问。

    文件内容:

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    # A.py
    class A:
        def __init__(self):
            self.text = "A"
    
    class _B:
        def __init__(self):
            self.text = "B
    
    # test.py
    from A import *
    a = A()
    print(a.__dict__)
    
    b = _B()
    print(b.__dict__)
    

    执行结果:
    在这里插入图片描述
    可以看到我们导入了A.py中所有的类,但其实_B并没有被导入,但是我们可以通过别的方式访问这个类,修改我们的test.py文件为以下内容。

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    import A
    a = A.A()
    print(a.__dict__)
    
    b = A._B()
    print(b.__dict__)
    

    在这里插入图片描述
    除了不能通过from module import *这种方式导入外,跟公有类并没有差别

    展开全文
  • python下划线和双下划线

    千次阅读 2018-08-12 15:41:41
    下划线 在类中,带有前导下划线的... 类似”__spam”格式的任何标识符(至少有两个前导下划线,最多一个尾部下划线)在python底层都会被修改成”_classname__spam”,其中classname是当前的类名。这种修改(mangli...

    单下划线

    单下划线开头的命名方式被常用于模块中,在一个模块中以单下划线开头的变量和方法会被默认划入模块内部范围。当使用 from my_module import * 导入时,单下划线开头的变量和方法是不会被导入的。但使用 import my_module 导入的话,仍然可以用 my_module._var 这样的形式访问属性或方法。

    单下划线结尾的命名方式也存在,但是不常用,其实也不推荐用。这种命名方式的作用就是为了和 python 的一些内置关键词区分开来,假设我们想给一个变量命名为 class,但是这会跟 python 的关键词 class 冲突,所以我们只好退一步使用单下划线结尾命名,也就是 class_。


    双下划线

    双下划线开头和结尾的是一些 python 的“魔术”对象,如类成员的 __init__、__del__、__add__、__getitem__ 等,以及全局的__file__、__name__ 等。 python 官方推荐永远不要将这样的命名方式应用于自己的变量或函数,而是按照文档说明来使用。

    双下划线开头的命名方式有实际的作用,采用这种命名的变量或方法无法直接通过 “对象名.变量名(方法名)” 这样的方式访问。

    看看python官方文档中的解释:

    类似”__spam”格式的任何标识符(至少有两个前导下划线,最多一个尾部下划线)在python底层都会被修改成”_classname__spam”,其中classname是当前的类名。这种修改(mangling)不会考虑标识符的语法位置,因此可以用来定义类私有实例和类变量、方法、全局变量,甚至是存储在实例中的变量。

    对标识符修改(Name mangling)的说明:

    名称修改旨在为类提供一种简单的方法来定义“私有”实例变量和方法,而不必担心派生类定义的实例变量,或者通过类外部的代码来修改实例变量。请注意,设计这种标识符的修改主要是为了避免一些在无意中可能造成的代码事故,避免不了那些执意要访问或者修改那些已经被视为私有的变量的行为。


    开始验证:

    #实现一个简单的类
    class MyClass():
         def __init__(self):
                self._semiprivate = "Hello"
                self.__superprivate = "world!"
    #创建一个实例
    mc = MyClass()
    
    #查看实例mc的字典,里面存放了该实例的变量
    print(mc.__dict__) 
    #输出:{'_semiprivate': 'Hello', '_MyClass__superprivate': 'world!'}
    #可以看到Name mangling的效果了:'__superprivate'被修改为'_MyClass__superprivate'
    #所以调用mc.__superprivate是肯定要出错的~
    
    print(mc._semiprivate) #输出:Hello
    print(mc._MyClass__superprivate)  #输出:world!
    
    print(mc.__superprivate)  
    #报错:AttributeError: 'MyClass' object has no attribute '__superprivate'

    参考:stackoverflow知乎

    展开全文
  • 变量名的定义有五种常见的定义形式: xx:公有变量 _xx:单前置下划线,称为保护变量,不能通过from XXX import xxx导入,只有类对象和子类对象能访问到这个数据。...xx_: 单后置下划线,用于避免与Python关键词...

    变量名的定义有五种常见的定义形式:

    1. xx:公有变量
    2. _xx:单前置下划线,称为保护变量,不能通过from XXX import xxx导入,只有类对象和子类对象能访问到这个数据。_xx 实现了模块级别的私有化。
    3. __xx: 双前置下划线,用于声明变量或者方法私有,无法在外部直接访问,只能在类的内部调用。
    4. __xx__ :双前后下划线,系统定义名字,例如:_init_,不要自己定义这样格式的变量名字。
    5. xx_: 单后置下划线,用于避免与Python关键词的冲突

    我们一起来看一个例子:

    class Person(object):
        def __init__(self, name, age, taste):
            self.name = name
            self._age = age                             
            self.__taste = taste                   
    
        def showperson(self):
            print(self.name)
            print(self._age)
            print(self.__taste)
    
        def dowork(self):
            self._work()
            self.__away()
    
        def _work(self):
            print('my _work')
    
        def __away(self):
            print('my __away')
    
    
    class Student(Person):
        def construction(self, name, age, taste):
            self.name = name
            self._age = age 
            self.__taste = taste
    
        def showstudent(self):
            print(self.name)
            print(self._age)
            print(self.__taste)
    
        @staticmethod
        def testbug():
            _Bug.showbug()
    
    # 模块内可以访问,当from  cur_module import *时,不导入
    class _Bug(object):
        @staticmethod
        def showbug():
            print("showbug")
    
    s1 = Student('jack', 25, 'football')
    s1.showperson()
    print('*'*20)  
    """
    上面三行代码的输出结果:
    jack
    25
    football
    ********************
    """                                 
    # s1.showstudent()
    """
    上述代码执行结果:
    AttributeError: 'Student' object has no attribute '_Student__taste'
    原因是__taste是私有属性,导致访问错误。
    """ 
    s1.construction('rose', 30, 'basketball')
    s1.showperson()
    print('*'*20)
    """
    上述三行代码执行的结果为:
    rose
    30
    football
    ********************
    """
    s1.showstudent()
    print('*'*20)
    """
    上述两行代码的输出结果:
    rose
    30
    basketball
    ********************
    """
    Student.testbug()
    """
    上述代码的执行结果:
    showbug
    """
    s1._work()  
    s1.__away()    # __away()是一个私有方法
    """
    上面两行代码的输出为:
    my _work
    Traceback (most recent call last):
      File "exercise.py", line 60, in <module>
        s1.__away()
    AttributeError: 'Student' object has no attribute '__away'
    """
    

    总结

    1. 父类中属性和方法名为 __名字 的,子类不继承,子类也不访问。
    2. 如果在子类中向 __名字 赋值,那么会在子类中定义的一个与父类相同名字的属性,例如:Student类中的 construction方法。
    3. _名字 的变量、函数、类在使用from xxx import * 时都不会被导入。
    展开全文
  • python下划线/双下划线使用总结

    万次阅读 多人点赞 2015-05-22 16:18:18
    python下划线/双下划线使用总结 时间:2013-10-08 10:56来源:www.chengxuyuans.com Python下划线作为变量前缀和后缀指定特殊变量/方法。 主要存在四种情形 1. 1. object # public  2. __...
  • Python下划线命名模式 - 小结 以下是一个简短的小结,即“速查表”,罗列了我在本文中谈到的五种Python下划线模式的含义: ---------------------------------------------------------------------------------...
  • Python常见下划线

    2018-05-05 21:20:00
    python中常见的下划线意义 Python中常常使用下划线里对变量进行修饰,通常作为变量的前缀或者后缀出现,被修饰的变量一般存在特殊的用法: _XXX:不能被from module import _XXX导入,这种情况下的_XXX被称为...
  • python下划线的使用

    2018-03-08 04:13:15
    python下划线最常见的是,作为字符用于命名变量,但是不同于a b c等字符,它有一些特殊的用法,有的是程序设计使然,有的是编程习惯约定俗成。 python下划线主要使用于一下四个场景 表示最近输出结果 表示没用...
  • 1. 表示刚才输出的内容用下划线表示最近一次输出的内容,这个在很多教程问答中出现,请认真看下面这个:使用python3命令进入python的解释器状态:第一行输入s='a,b,c,d'然后就回车第二行输入_,报错notdefined未定义...
  • python下划线作为变量前缀和后缀指定特殊变量/方法。主要存在四种情形object # public__object__ # special, python system use, user should not define like it__object # private (name mangling during ...
  • python 中的 @property装饰器 既要保护类的封装特性,又要让开发者可以使用“对象.属性”的方式操作操作类属性,除了使用 property() 函数,Python 还提供了 @property 装饰器。通过 @property 装饰器,可以直接通过...
  • 前后双下划线,我之前的理解是python程序中的类似meta data的信息,例如__name__变量前单下划线python类中的私有变量或函数单独下划线,用来表示上一个输出(在python Interactive console中)。常见用法for _ in ...
  • Python下划线作为变量前缀和后缀指定特殊变量/方法。 主要存在四种情形 1. 1. object # public  2. __object__ # special, python system use, user should not define like it  3. __object # private (name...
  • 下划线(_): 在交互解释器中,表示上一条语句执行输出的结果。另外,单下划线还可以作为特殊的临时变量,表示在后面将不会在用到这个变量。 名称前的单下划线:只能在内部使用,是API中非公开的部分,不能被 ...
  • python变量下划线小结

    千次阅读 2019-02-12 20:45:17
    一个python脚本,比如 hello.py,就是一个模块,这个模块的名字叫hello;一个模块既可以被其它模块导入(importable),也可以被直接执行(executable). __name__是python的内置变量。如果一个模块是被直接执行的...
  • Python下划线详解

    2019-03-06 15:21:07
    python下划线最常见的是,作为字符用于命名变量,但是不同于a b c等字符,它有一些特殊的用法,有的是程序设计使然,有的是编程习惯约定俗成。 python下划线主要使用于一下四个场景 表示最近输出结果 表示...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 41,750
精华内容 16,700
关键字:

python输出下划线

python 订阅