單下劃線與雙下劃線的區別單下劃線(_)名稱前的單下劃線(如:_name)名稱前的雙下劃線(如:__name)名稱先後的雙下劃線(如:_ init _)總結python
Python用下劃線做爲前綴和後綴指定特殊變量和定義方法,主要有以下四種形式:面試
只有單劃線的狀況,主要有兩種使用場景:shell
一、在交互式解釋器中,單下劃線「_」表明的是上一條執行語句的結果。若是單下劃線前面沒有語句執行,交互式解釋器將會報單下劃線沒有定義的錯誤。也能夠對單下劃線進行賦值操做,這時單下劃線表明賦值的結果。可是通常不建議對單下劃線進行賦值操做,由於單下劃線內建標識符。數據庫
1>>> _
2Traceback (most recent call last):
3 File "<pyshell#0>", line 1, in <module>
4 _
5NameError: name '_' is not defined
6>>> "python"
7'python'
8>>> _
9'python'
10>>> _="Java"
11>>> _
12'Java'
13>>>
二、單下劃線「_」還能夠做爲特殊的臨時變量。若是一個變量在後面不會再用到,而且不想給這個變量定義名稱,這時就能夠用單下劃線做爲臨時性的變量。好比對for循環語句遍歷的結果元素並不感興趣,此時就能夠用單下劃線表示。網絡
1# _ 這個變量在後面不會用到
2for _ in range(5):
3 print("Python")
當在屬性和方法前面加上單下劃線「_」,用於指定屬性和方法是「私有」的。可是Python不像Java同樣具備私有屬性、方法、類,在屬性和方法以前加單下劃線,只是表明該屬性、方法、類只能在內部使用,是API中非公開的部分。若是用from import * 和 from import * 時,這些屬性、方法、類將不被導入。app
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 1, in <module>
7 _otherValue
8NameError: name '_otherValue' is not defined
9>>> method()
10我是普通方法
11>>> _otherMethod()
12Traceback (most recent call last):
13 File "<pyshell#6>", line 1, in <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 1, in <module>
21 w=_WClass()
22NameError: name '_WClass' is not defined
從上面的結果能夠看出,不論是屬性、方法和類,只要名稱前面加了單下劃線,都不能導出。測試
若是對程序進行修改,將在開頭加入_ all _,結果會是如何?ui
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文件導入,進行測試。spa
1>>> from Test import *
2>>> value
3'Java'
4>>> _otherValue
5'Python'
6>>> method()
7Traceback (most recent call last):
8 File "<pyshell#4>", line 1, in <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 1, in <module>
16 p=PClass()
17NameError: name 'PClass' is not defined
18>>> w= _WClass()
19單下劃線類的初始化
_ all _是一個字符串列表,不論是普通的仍是單下劃線的屬性、方法和類,都將導出來,使用其餘不在這個字符列表上的屬性、方法和類,都會報未定義的錯誤。
不論是屬性、方法和類,只要名稱前面加了單下劃線,都不能導入。除非是模塊或包中的「_ all_」列表顯式地包含了它們。
咱們先看看下面的程序:
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 18, in <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調用BMethod的method方法
5__method in class Amethod!
6anthod method in class AMethod!
7
運行結果並非咱們想要的結果,b.method()並無調用BMethod類的__method方法,而這個設計的實際目的是爲了不父類的方法被子類輕易的覆蓋。
在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,學習最實用的數據庫技術。 ........................................................................................................................ |