內容目錄
單下划線與雙下划線的區別單下划線(_)名稱前的單下划線(如:_name)名稱前的雙下划線(如:__name)名稱前后的雙下划線(如:_ init _)總結
單下划線與雙下划線的區別
Python用下划線作為前綴和后綴指定特殊變量和定義方法,主要有如下四種形式:
- 單下划線(_)
- 名稱前的單下划線(如:_name)
- 名稱前的雙下划線(如:__name)
- 名稱前后的雙下划線(如:_ init _)
單下划線(_)
只有單划線的情況,主要有兩種使用場景:
1、在交互式解釋器中,單下划線“_”代表的是上一條執行語句的結果。如果單下划線前面沒有語句執行,交互式解釋器將會報單下划線沒有定義的錯誤。也可以對單下划線進行賦值操作,這時單下划線代表賦值的結果。但是一般不建議對單下划線進行賦值操作,因為單下划線內建標識符。
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>>>
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 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 _,結果會是如何?
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 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_”列表顯式地包含了它們。
名稱前的雙下划線(如:__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 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方法,而這個設計的實際目的是為了避免父類的方法被子類輕易的覆蓋。
名稱前后的雙下划線(如:_ 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,學習最實用的數據庫技術。 ........................................................................................................................ |
![]() |
![]() |