zoukankan      html  css  js  c++  java
  • 单下划线与双下划线的区别

    内容目录

    单下划线与双下划线的区别单下划线(_)名称前的单下划线(如:_name)名称前的双下划线(如:__name)名称前后的双下划线(如:_ init _)总结

    单下划线与双下划线的区别

    ​ Python用下划线作为前缀和后缀指定特殊变量和定义方法,主要有如下四种形式:

    • 单下划线(_)
    • 名称前的单下划线(如:_name)
    • 名称前的双下划线(如:__name)
    • 名称前后的双下划线(如:_ init _

    单下划线(_)

    ​ 只有单划线的情况,主要有两种使用场景:

    ​ 1、在交互式解释器中,单下划线“_”代表的是上一条执行语句的结果。如果单下划线前面没有语句执行,交互式解释器将会报单下划线没有定义的错误。也可以对单下划线进行赋值操作,这时单下划线代表赋值的结果。但是一般不建议对单下划线进行赋值操作,因为单下划线内建标识符。

     1>>> _
    2Traceback (most recent call last):
    3  File "<pyshell#0>", line 1in <module>
    4    _
    5NameError: name '_' is not defined
    6>>> "python"
    7'python'
    8>>> _
    9'python'
    10>>> _="Java"
    11>>> _
    12'Java'
    13>>> 

    2、单下划线“_”还可以作为特殊的临时变量。如果一个变量在后面不会再用到,并且不想给这个变量定义名称,这时就可以用单下划线作为临时性的变量。比如对for循环语句遍历的结果元素并不感兴趣,此时就可以用单下划线表示。

    1# _ 这个变量在后面不会用到
    2for _ in range(5):
    3    print("Python")

    名称前的单下划线(如:_name)

    ​ 当在属性和方法前面加上单下划线“_”,用于指定属性和方法是“私有”的。但是Python不像Java一样具有私有属性、方法、类,在属性和方法之前加单下划线,只是代表该属性、方法、类只能在内部使用,是API中非公开的部分。如果用from import * 和 from import * 时,这些属性、方法、类将不被导入。

     1# Test.py 文件
    2
    3#普通属性
    4value="Java"
    5
    6#单下划线属性
    7_otherValue="Python"
    8
    9
    10#普通方法
    11def  method():
    12    print("我是普通方法")
    13
    14#单下划线方法
    15def _otherMethod():
    16    print("我是单下划线方法")
    17
    18#普通类
    19class PClass(object):
    20
    21    def __init__(self):
    22        print("普通类的初始化")
    23
    24#单下划线类
    25class _WClass(object):
    26
    27    def __init__(self):
    28        print("单下划线类的初始化")

    ​ 将上述的Test.py文件导入,进行测试。

     1>>> from Test import *
    2>>> value
    3'Java'
    4>>> _otherValue
    5Traceback (most recent call last):
    6  File "<pyshell#4>", line 1in <module>
    7    _otherValue
    8NameError: name '_otherValue' is not defined
    9>>> method()
    10我是普通方法
    11>>> _otherMethod()
    12Traceback (most recent call last):
    13  File "<pyshell#6>", line 1in <module>
    14    _otherMethod()
    15NameError: name '_otherMethod' is not defined
    16>>> p=PClass()
    17普通类的初始化
    18>>> w=_WClass()
    19Traceback (most recent call last):
    20  File "<pyshell#8>", line 1in <module>
    21    w=_WClass()
    22NameError: name '_WClass' is not defined

    ​ 从上面的结果可以看出,不管是属性、方法和类,只要名称前面加了单下划线,都不能导出。

    ​ 如果对程序进行修改,将在开头加入_ all _,结果会是如何?

     1# Test.py 文件
    2
    3#将普通属性、单下划线的属性、方法、和类加入__all__列表
    4__all__=["value""_otherValue","_otherMethod","_WClass"]
    5
    6#普通属性
    7value="Java"
    8
    9#单下划线属性
    10_otherValue="Python"
    11
    12#普通方法
    13def  method():
    14    print("我是普通方法")
    15
    16#单下划线方法
    17def _otherMethod():
    18    print("我是单下划线方法")
    19
    20#普通类
    21class PClass(object):
    22
    23    def __init__(self):
    24        print("普通类的初始化")
    25
    26#单下划线类
    27class _WClass(object):
    28
    29    def __init__(self):
    30        print("单下划线类的初始化")

    ​ 将上述修改过的Test.py文件导入,进行测试。

     1>>> from Test import *
    2>>> value
    3'Java'
    4>>> _otherValue
    5'Python'
    6>>> method()
    7Traceback (most recent call last):
    8  File "<pyshell#4>", line 1in <module>
    9    method()
    10NameError: name 'method' is not defined
    11>>> _otherMethod()
    12我是单下划线方法
    13>>> p=PClass()
    14Traceback (most recent call last):
    15  File "<pyshell#6>", line 1in <module>
    16    p=PClass()
    17NameError: name 'PClass' is not defined
    18>>> w= _WClass()
    19单下划线类的初始化

    _ all _是一个字符串列表,不管是普通的还是单下划线的属性、方法和类,都将导出来,使用其他不在这个字符列表上的属性、方法和类,都会报未定义的错误。

    ​ 不管是属性、方法和类,只要名称前面加了单下划线,都不能导入。除非是模块或包中的“_ all_”列表显式地包含了它们。

    名称前的双下划线(如:__name)

    ​ 我们先看看下面的程序:

     1class Method(object):
    2    # 构造器方法
    3    def __init__(self, name):
    4        # 双下划线属性
    5        self.__name = name
    6    # 普通方法
    7    def sayhello(self):
    8        print("Method say hello!")
    9    # 双下划线方法
    10    def __sayhi(self):
    11        print("Method say hi!")
    12
    13# 初始化Method
    14m = Method("Python")
    15# 调用sayhello方法
    16m.sayhello()
    17# 调用sayhi方法
    18m.__sayhi()
    19# 输出属性__name
    20print(m.__name)

    ​ 上面的程序定义了一个类,这个类有三个方法,一个构造器方法,一个普通方法,一个双下划线方法,以及包括一个双下划线的属性。上面的结果输出的是什么?很多读者可能认为输出的结果如下:

    1Method say hello!
    2Method say hi!
    3Python

    ​ 那么恭喜你,上面的输出结果是错误的,实际输出的结果为:

    1Method say hello!
    2Traceback (most recent call last):
    3  File "<encoding error>", line 18in <module>
    4AttributeError: 'Method' object has no attribute '__sayhi'

    ​ 实际上,当对象调用__sayhi()方法时,将会报Method类没有这个方法属性的错误。那如何去调用以双下划线开头的方法和属性?Python这样设计的目的是什么?

    ​ 首先回答第一个问题,读者看完下面的程序就知道怎么调用了。

     1class Method(object):
    2
    3    def __init__(self, name):
    4        self.__name = name
    5
    6    def sayhello(self):
    7        print("Method say hello!")
    8
    9    def __sayhi(self):
    10        print("Method say hi!")
    11
    12
    13# 初始化Method
    14m = Method("Python")
    15# 调用sayhello方法
    16m.sayhello()
    17# 调用sayhi方法
    18#m.__sayhi()
    19m._Method__sayhi()
    20# 输出属性__name
    21#print(m.__name)
    22print(m._Method__name)

    ​ 输出结果如下:

    1Method say hello!
    2Method say hi!
    3Python

    ​ 我们从上面的程序中可以很清楚的看到,如果要调用以双下划线开头的方法和属性,只要以“类名_方法(属性)”的形式就可以实现方法或者属性的访问了。类前面是单下划线,类名后面是双下划线,然后再加上方法或者属性。但是并不建议调用,因为这是Python内部进行调用的形式。

    ​ 回答完第一个问题,我们看看第二个问题,Python这样设计的目的是什么?

    ​ 有很多人认为,Python以双下划线开头的方法和属性表示私有的方法和属性,实际上这样的理解不太准确,也不能说完全错误的。但是这并不是Python设计的目的和初衷,我们先看看下面一段程序和程序运行结果:

     1class AMethod(object):
    2
    3    def __method(self):
    4        print("__method in class Amethod!")
    5
    6    def method(self):
    7        self.__method()
    8        print("anthod method in class AMethod!")
    9
    10class BMethod(AMethod):
    11
    12    def __method(self):
    13        print("__method in class Bmethod!")
    14
    15
    16if __name__=="__main__":
    17
    18    print("调用AMethod的method方法")
    19    a = AMethod()
    20    a.method()
    21
    22    print("调用BMethod的method方法")
    23    b = BMethod()
    24    b.method()

    ​ 上面的程序定义了两个类,一个是AMethod类,另外一个是继承了AMethod类的BMethod类。在AMethod类中,定义了两个方法,一个是以双下划线开头的__method方法,另外一个是普通方法。在BMethod类中,重写了AMethod类中的__method方法。

    ​ 程序运行结果:

    1调用AMethod的method方法
    2__method in class Amethod!
    3anthod method in class AMethod!
    4调用BMethodmethod方法
    5__method in class Amethod!
    6anthod method in class AMethod!
    7

    ​ 运行结果并不是我们想要的结果,b.method()并没有调用BMethod类的__method方法,而这个设计的实际目的是为了避免父类的方法被子类轻易的覆盖。

    名称前后的双下划线(如:_ init _

    ​ 在Python类中,我们可以常常看到类似于“_ init _ ”的方法,这表示在Python内部调用的方法,一般不建议在程序中调用。比如,当调用len()方法时,实际上调用了 Python中内部的 _ len _ 方法,虽然不建议调用这种以双下划线开头以及结尾的方法,但是可以对这些方法进行重写。比如下面的例子:

     1class Number(object):
    2
    3    def __init__(self, number):
    4        self.number = number
    5
    6    def __add__(self, number):
    7        # 重写方法,返回两个数的差值
    8        return self.number - number
    9
    10    def __sub__(self, number):
    11        # 重写方法,返回两个数的和
    12        return self.number + number
    13
    14    def __str__(self):
    15        # 重写方法,返回字符串
    16        return str(self.number)
    17
    18
    19num = Number(100)
    20print(num) # 100 调用了__str__方法
    21print(num+50# 50 + 调用了__add__方法
    22print(num-20# 120 -调用了__sub__方法

    ​ 相信看了上面所有对Python中下划线作用的讲解,完全能够理解上述四种下划线所表示的意义。最后将对上面的,进行总结。

    总结

    • 单下划线(_): 在交互解释器中,表示上一条语句执行输出的结果。另外,单下划线还可以作为特殊的临时变量,表示在后面将不会在用到这个变量。

    • 名称前的单下划线:只能在内部使用,是API中非公开的部分,不能被 import * 和 from import *导入程序中,除非在all列表中包含了以单下划线开头的属性、方法以及类。

    • 名称前的双下划线:以双下划线开头的属性、方法表示避免父类的属性和方法被子类轻易的覆盖,一般不建议这样定义属性和方法,除非你自己将要做什么。

    • 名称前后的双下划线:这类方法是Python内部定义的方法,你可以重写这些方法,这样Python就可以调用这个重写的方法以及利用操作符。



    About Me

    ........................................................................................................................

    ● 本文作者:小麦苗,部分内容整理自网络,若有侵权请联系小麦苗删除

    ● 本文在itpub(http://blog.itpub.net/26736162)、博客园(http://www.cnblogs.com/lhrbest)和个人weixin公众号(xiaomaimiaolhr)上有同步更新

    ● 本文itpub地址:http://blog.itpub.net/26736162

    ● 本文博客园地址:http://www.cnblogs.com/lhrbest

    ● 本文pdf版、个人简介及小麦苗云盘地址:http://blog.itpub.net/26736162/viewspace-1624453/

    ● 数据库笔试面试题库及解答:http://blog.itpub.net/26736162/viewspace-2134706/

    ● DBA宝典今日头条号地址:http://www.toutiao.com/c/user/6401772890/#mid=1564638659405826

    ........................................................................................................................

    ● QQ群号:230161599(满)、618766405

    ● weixin群:可加我weixin,我拉大家进群,非诚勿扰

    ● 联系我请加QQ好友646634621,注明添加缘由

    ● 于 2019-01-01 06:00 ~ 2019-01-31 24:00 在魔都完成

    ● 最新修改时间:2019-01-01 06:00 ~ 2019-01-31 24:00

    ● 文章内容来源于小麦苗的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解

    ● 版权所有,欢迎分享本文,转载请保留出处

    ........................................................................................................................

    小麦苗的微店https://weidian.com/s/793741433?wfr=c&ifr=shopdetail

    小麦苗出版的数据库类丛书http://blog.itpub.net/26736162/viewspace-2142121/

    小麦苗OCP、OCM、高可用网络班http://blog.itpub.net/26736162/viewspace-2148098/

    小麦苗腾讯课堂主页https://lhr.ke.qq.com/

    ........................................................................................................................

    使用weixin客户端扫描下面的二维码来关注小麦苗的weixin公众号(xiaomaimiaolhr)及QQ群(DBA宝典)、添加小麦苗weixin,学习最实用的数据库技术。

    ........................................................................................................................

    欢迎与我联系

     

     



  • 相关阅读:
    spring-boot启动debug信息中non-fatal error解决
    spring-boot-sample-web-jsp
    How to configure spring boot through annotations in order to have something similar to <jsp-config> in web.xml?
    mybatis支持属性使用驼峰的命名
    No handler for type [text] declared on field [content]
    android自定义控件库
    Android 百分比布局库(percent-support-lib) 解析与扩展
    Android 高清加载巨图方案 拒绝压缩图片
    Android 热补丁动态修复框架小结
    AndroidAutoLayout 屏幕适配
  • 原文地址:https://www.cnblogs.com/lhrbest/p/10281563.html
Copyright © 2011-2022 走看看