Python 用下划线作为前缀和后缀指定特殊变量和定义方法,主要有如下四种形式:
l 单下划线( _ )
l 名称前的单下划线(如: _name )
l 名称前的双下划线(如: __name )
l 名称前后的双下划线(如 :__init__ )
(一) 单下划线( _ )
只有单 下 划线的情况,主要有两种使用场景:
1 、在交互式解释器中,单下划线“ _ ”代表的是上一条执行语句的结果。如果单下划线前面没有语句执行, 那么 交互式解释器将会报单下划线没有定义的错误。也可以对单下划线进行赋值操作,这时单下划线代表赋值的结果。但是一般不建议对单下划线进行赋值操作,因为单下划线内建标识符。
>>> _
Traceback (most recent call last):
File "
_
NameError: name '_' is not defined
>>> "python"
'python'
>>> _
'python'
>>> _="Java"
>>> _
'Java'
>>>
2 、单下划线“ _ ”还可以作为特殊的临时变量。如果一个变量在后面不会再用到,并且不想给这个变量定义名称, 那么 这时就可以用单下划线作为临时性的变量。 例如, 对 for 循环语句遍历的结果元素并不感兴趣,此时就可以用单下划线表示。
# _ 这个变量在后面不会用到
for _ in range(5):
print("Python")
(二) 名称前的单下划线(如: _name )
当在属性和方法前面加上单下划线 “ _ ”,用于指定属性和方法是“私有”的。但是 Python 不像 Java 一样具有私有属性、方法、类,在属性和方法之前加单下划线,只是代表该属性、方法、类只能在内部使用,是 API 中非公开的部分。如果用 from
# Test.py 文件
# 普通属性
value="Java"
# 单下划线属性
_otherValue="Python"
# 普通方法
def method():
print(" 我是普通方法 ")
# 单下划线方法
def _otherMethod():
print(" 我是单下划线方法 ")
# 普通类
class PClass(object):
def __init__(self):
print(" 普通类的初始化 ")
# 单下划线类
class _WClass(object):
def __init__(self):
print(" 单下划线类的初始化 ")
将上述的 Test.py 文件导入,进行测试。
>>> from Test import *
>>> value
'Java'
>>> _otherValue
Traceback (most recent call last):
File "
_otherValue
NameError: name '_otherValue' is not defined
>>> method()
我是普通方法
>>> _otherMethod()
Traceback (most recent call last):
File "
_otherMethod()
NameError: name '_otherMethod' is not defined
>>> p=PClass()
普通类的初始化
>>> w=_WClass()
Traceback (most recent call last):
File "
w=_WClass()
NameError: name '_WClass' is not defined
从上面的结果可以看出,不管是属性、方法和类,只要 在 名称前面加了单下划线,都不能导出。如果对程序 Test.py 进行修改,在 文件 开头加入 __all__ , 结果会是如何?
# 将普通属性、单下划线的属性、方法、和类加入 __all__ 列表
__all__=["value" , "_otherValue","_otherMethod","_WClass"]
修改后继续测试:
>>> from Test import *
>>> value
'Java'
>>> _otherValue
'Python'
>>> method()
Traceback (most recent call last):
File "
method()
NameError: name 'method' is not defined
>>> _otherMethod()
我是单下划线方法
>>> p=PClass()
Traceback (most recent call last):
File "
p=PClass()
NameError: name 'PClass' is not defined
>>> w= _WClass()
单下划线类的初始化
__all__ 是一个字符串列表,不管是普通的还是单下划线的属性、方法和类,都将导出来,使用其他不在这个字符列表上的属性、方法和类,都会报未定义的错误。不管是属性、方法和类,只要名称前面加了单下划线,都不能导入。除非是模块或包中的“ __all__ ”列表显式地包含了它们。
(三) 名称前的双下划线(如: __name )
先看看下面的程序:
class Method(object):
# 构造器方法
def __init__(self, name):
# 双下划线属性
self.__name = name
# 普通方法
def sayhello(self):
print("Method say hello!")
# 双下划线方法
def __sayhi(self):
print("Method say hi!")
# 初始化 Method
m = Method("Python")
# 调用 sayhello 方法
m.sayhello()
# 调用 sayhi 方法
m.__sayhi()
# 输出属性 __name
print(m.__name)
上面的程序定义了一个类,这个类有三个方法,一个构造器方法,一个普通方法,一个双下划线方法,以及包括一个双下划线的属性。上面 的 输出结果 是 :
Method say hello!
Traceback (most recent call last):
File "
AttributeError: 'Method' object has no attribute '__sayhi'
实际上,当对象调用 __sayhi() 方法时,将会报 Method 类没有这个方法属性的错误。那如何去调用以双下划线开头的方法和属性? Python 这样设计的目的是什么?
首先回答第一个问题,读者看完下面的程序就知道怎么调用了。
class Method(object):
def __init__(self, name):
self.__name = name
def sayhello(self):
print("Method say hello!")
def __sayhi(self):
print("Method say hi!")
# 初始化 Method
m = Method("Python")
# 调用 sayhello 方法
m.sayhello()
# 调用 sayhi 方法
#m.__sayhi()
m._Method__sayhi()
# 输出属性 __name
#print(m.__name)
print(m._Method__name)
输出结果如下:
Method say hello!
Method say hi!
Python
从上面的程序中可以很清楚的看到,如果要调用以双下划线开头的方法和属性,只要以 “ _ 类名 __ 方法(属性)”的形式就可以实现方法或者属性的访问了。类前面是单下划线,类名后面是双下划线,然后再加上方法或者属性。但是并不建议调用,因为这是 Python 内部进行调用的形式。
回答完第一个问题,我们看看第二个问题, Python 这样设计的目的是什么?
有很多人认为, Python 以双下划线开头的方法和属性表示私有的方法和属性,实际上这样的理解不太准确,也不能说完全错误的。但是这并不是 Python 设计的目的和初衷,我们先看看下面一段程序和程序运行结果 :
class AMethod(object):
def __method(self):
print("__method in class Amethod!")
def method(self):
self.__method()
print("anthod method in class AMethod!")
class BMethod(AMethod):
def __method(self):
print("__method in class Bmethod!")
if __name__=="__main__":
print(" 调用 AMethod 的 method 方法 ")
a = AMethod()
a.method()
print(" 调用 BMethod 的 method 方法 ")
b = BMethod()
b.method()
上面的程序定义了两个类,一个是 AMethod 类,另外一个是继承了 AMethod 类的 BMethod 类。在 AMethod 类中,定义了两个方法,一个是以双下划线开头的 __method 方法,另外一个是普通方法。在 BMethod 类中,重写了 AMethod 类中的 __method 方法。
程序运行结果:
调用 AMethod 的 method 方法
__method in class Amethod!
anthod method in class AMethod!
调用 BMethod 的 method 方法
__method in class Amethod!
anthod method in class AMethod!
运行结果并不是我们想要的结果, b.method() 并没有调用 BMethod 类的 __method 方法,而这个设计的实际目的是为了避免父类的方法被子类轻易的覆盖。
(四) 名称前后的双下划线(如 : __init__ )
在 Python 类中,可以常常看到类似于“ __init__ ”的方法,这表示在 Python 内部调用的方法,一般不建议在程序中调用。比如,当调用 len() 方法时,实际上调用了 Python 中内部的 __len__ 方法,虽然不建议调用这种以双下划线开头以及结尾的方法,但是可以对这些方法进行重写。比如下面的例子:
class Number(object):
def __init__(self, number):
self.number = number
def __add__(self, number):
# 重写方法,返回两个数的差值
return self.number - number
def __sub__(self, number):
# 重写方法,返回两个数的和
return self.number + number
def __str__(self):
# 重写方法,返回字符串
return str(self.number)
num = Number(100)
print(num) # 100 调用了 __str__ 方法
print(num+50) # 50 + 调用了 __add__ 方法
print(num-20) # 120 - 调用了 __sub__ 方法
相信看了上面所有对 Python 中下划线作用的讲解,完全能够理解上述四种下划线所表示的意义。最后将对上面的,进行总结。
(五) 总结
l 单下划线( _ ) : 在交互解释器中,表示上一条语句执行输出的结果。另外,单下划线还可以作为特殊的临时变量,表示在后面将不会在用到这个变量。
l 名称前的单下划线:只能在内部使用,是 API 中非公开的部分,不能被
l 名称前的双下划线:以双下划线开头的属性、方法表示避免父类的属性和方法被子类轻易的覆盖,一般不建议这样定义属性和方法,除非你自己将要做什么。
l 名称前后的双下划线:这类方法是 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, 学习最实用的数据库技术。
........................................................................................................................ |
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26736162/viewspace-2564637/,如需转载,请注明出处,否则将追究法律责任。