【Python基础】关于Python的前后、单双下划线作用
python的各種下劃線
在Python中,可能最常見的就是各種常量、變量、函數、方法前后添加的那些下劃線了。有前面加的、后面加的,加一個的,加兩個的,看到頭暈。那么,你對這些知識都掌握了嗎 ?讓我們先來做一個自測吧。
題目:說明以下四個例子輸出的結果分別是什么。
自測題各位,請開始你的表演,來看看以上4段代碼分別輸出的結果是什么?OK,記住你的答案,等看完文章解開謎底后,再來看看的答對了沒。
單前導下劃線
單前導下劃線(_xxx),作為Python的命名約定,表示僅供內部使用。但注意這個命名約定,在類中你使用單前導線聲明的變量,**依然可以在外部直接訪問。**那這種命名約定還有什么意義呢?有!當代碼使用
from modlue import *?
導入某個模塊時,單前導線這種定義方式的屬性,不會被導入。舉例:
#?demo1.py Name?=?"清風" _Age?=?18#?demo2.py from?demo1?import?*print(print(Name,_Age))#output: NameError:?name?'_Age'?is?not?defined??正常的情況是如上結果,但是萬事無絕對,面試官的陰人考點來了:
__all__ = ["Name", "_Age"]
當demo1.py在開頭聲明如上,使用__all__單獨聲明了可導入內容時,可以正常導入。雖然使用起來矛盾,但是面試陰人必備有木有?
單末尾下劃線
單末尾下劃線(xxx_),按照PEP8規定,單末尾下劃線也是一個約定 用來避免與python關鍵字產生命名沖突。
例如:我們使用Beautifulsoup進行網頁解析,通過類方法定位時,會找某個標簽它的存在class=‘xxx’的情況,此時css的class與Python中的類重名,需要在class后添加單下劃線進行區分。類似場景還有很多,就不一一列舉了。
雙前導和雙末尾下劃線
日常開發中,最好避免在自己的程序中使用以雙下劃線(“dunders”)開頭和結尾的名稱,因為它是Python語言定義的一種特殊方法(魔法方法),我們熟知的__init__ 、__dict__ 、__getitem__等等。
但是,如果你非要使用這種寫法去聲明,那可真是無底坑...如果你聲明的變量不是內置的魔法方法,Python會將它當做普通的變量來操作。如果和內置的方法重名,要么重寫,要么因為功能沖突而引發報錯,所以不作死就不會死,還是別這么玩了。
雙前導下劃線
這個為什么放在最后,因為壓軸啊!雙前導下劃線,在面試中被考到的幾率太大了,尤其是那種長相猥瑣,心術不正的面試官,最愛問這個知識點,所以要牢記。
首先雙前導下劃線(__xxx)的命名,90%情況下是真切的私有變量、方法,剩下10%一會兒再說。下來說說雙前導下劃線的作用,既然為私有屬性,那么僅在當前類中可用,外部、子類均無法調用和繼承。知道這點寫代碼差不多夠了,但還差一點,拿文章開頭的最后一個例子來說
#?Test4 class?Root:def?__func(self):print('root')class?Child(Root):def?__init__(self):self.__func()Child()大家剛才的答案是什么,root?恭喜你,打錯了,結果是:
AttributeError: 'Child' object has no attribute '_Child__func'
不該是子類沒有的方法,繼承父類么,明明父類有,為什么會報錯。剛才我們說到了,雙前導下劃線是真切的私有變量、方法,無法被子類所繼承。如果我們把雙前導下劃線,變成了單前導下劃線(如Test3),那么結果是root。
不能繼承的問題明白了,但這個_Child__func是什么鬼?這就要說為什么剛才我說雙前導下劃線90%的情況下是真切的私有變量了、讓我們來看下面的例子:
class?Demo:def?__init__(self):self.__name?=?"清風Python"def?__say_hello(self):print(f"你好:{self.__name}")D?=?Demo() #?usually print(D.__name) D.__say_hello#?specially print(D._Demo__name) D._Demo__say_hello()我們定義一個Demo類,其中存在雙前導下劃線的__name __say_hello,當我們使用通常的調用方式時,是無法執行的,但Python的私有屬性聲明時,其實就是將某個私有屬性前添加單下劃線+類名,所以如果其實不存在什么私有屬性,我們可以通過_classname__privatefunc的方式實現強制調用。
那么,日常中我們能否盡量的避免這種方式呢?方法是有的,但是只能騙騙初學者,對有心人還是沒用,比如:
class?Demo:def?__init__(self):self.__money?=?100@propertydef?money(self):return?self.__money@money.setterdef?money(self,?pwd):passD?=?Demo() D.money?=?1000000 print(D.money)?#?依舊為100塊python的property裝飾器,可以將方法聲明為類的屬性,當某人調用D.money得到自己余額為100塊時,肯定想著我重新賦值余額秒變土豪,但真實的余額我們使用的是私有的self.__money。而通過property創建了一個money的屬性,當用戶對money賦值時,money.setter的方法是空的,你怎么賦值都是無用的(空的干嘛還要寫,因為不寫會報錯啊...AttributeError: can't set attribute)。
這樣看起來很完美啊,為什么說只能騙騙初學者?當你打印print(D.__dict__)時{'_Demo__money': 100}一目了然。
最后,文章開頭的測試題答案你做對了么?結果是:
child、root、root、報錯??你答對了么?
今天關于Python中下劃線的內容就到此為止,是否起到了穩固執行的效果呢?如果覺得有所收獲,歡迎分享給你的小伙伴們一起進步啊!
END
往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯 獲取本站知識星球優惠券,復制鏈接直接打開: https://t.zsxq.com/qFiUFMV 本站qq群704220115。加入微信群請掃碼:總結
以上是生活随笔為你收集整理的【Python基础】关于Python的前后、单双下划线作用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【迁移学习】隐私保护下的迁移算法
- 下一篇: 【算法基础】数据结构导论第三章-栈、队列