python中那些雙下劃線開頭得函式和變數

小小程序员ol發表於2024-05-21

Python中下劃線---完全解讀

Python 用下劃線作為變數字首和字尾指定特殊變數

_xxx 不能用from module import *匯入

__xxx__ 系統定義名字

__xxx 類中的私有變數名

核心風格:避免用下劃線作為變數名的開始。

因為下劃線對直譯器有特殊的意義,而且是內建識別符號所使用的符號,我們建議程式設計師避免用下劃線作為變數名的開始。一般來講,變數名_xxx被看作是“私有 的”,在模組或類外不可以使用。當變數是私有的時候,用_xxx來表示變數是很好的習慣。因為變數名__xxx__對Python 來說有特殊含義,對於普通的變數應當避免這種命名風格。

“單下劃線” 開始的成員變數叫做保護變數,意思是隻有類物件和子類物件自己能訪問到這些變數;
“雙下劃線” 開始的是私有成員,意思是隻有類物件自己能訪問,連子類物件也不能訪問到這個資料。

以單下劃線開頭_foo的代表不能直接訪問的類屬性,需透過類提供的介面進行訪問,不能用from xxx import *而匯入;以雙下劃線開頭的__foo代表類的私有成員;以雙下劃線開頭和結尾的__foo__代表python裡特殊方法專用的標識,如 __init__()代表類的建構函式。

現在我們來總結下所有的系統定義屬性和方法, 先來看下保留屬性:

>>> Class1.__doc__ # 型別幫助資訊 'Class1 Doc.' 
>>> Class1.__name__ # 型別名稱 'Class1' 
>>> Class1.__module__ # 型別所在模組 '__main__' 
>>> Class1.__bases__ # 型別所繼承的基類 (<type 'object'>,) 
>>> Class1.__dict__ # 型別字典,儲存所有型別成員資訊。
 <dictproxy object at 0x00D3AD70> 
#學習中遇到問題沒人解答?小編建立了一個Python學習交流群:153708845
>>> Class1().__class__ # 型別 <class '__main__.Class1'>
>>> Class1().__module__ # 例項型別所在模組 '__main__' 
>>> Class1().__dict__ # 物件字典,儲存所有例項成員資訊。 {'i': 1234}

接下來是保留方法,可以把保留方法分類:

類的基礎方法

序號 目的 所編寫程式碼 Python 實際呼叫
初始化一個例項 x = MyClass() x.__init__()
字串的“官方”表現形式 repr(x) x.__repr__()
字串的“非正式”值 str(x) x.__str__()
位元組陣列的“非正式”值 bytes(x) x.__bytes__()
格式化字串的值 format(x, format_spec) x.__format__(format_spec)
  • __init__() 方法的呼叫發生在例項被建立 之後 。如果要控制實際建立程序,請使用__new__()方法。
  • 按照約定,__repr__()方法所返回的字串為合法的 Python 表示式。
  • 在呼叫 print(x) 的同時也呼叫了 __str__() 方法。
  • 由於 bytes 型別的引入而從 Python 3 開始出現。

行為方式與迭代器類似的類

序號 目的 所編寫程式碼 Python 實際呼叫
遍歷某個序列 iter(seq) seq.__iter__()
從迭代器中獲取下一個值 next(seq) seq.__next__()
按逆序建立一個迭代器 reversed(seq) seq.__reversed__()
  • 無論何時建立迭代器都將呼叫 __iter__() 方法。這是用初始值對迭代器進行初始化的絕佳之處。
  • 無論何時從迭代器中獲取下一個值都將呼叫 __next__() 方法。
  • __reversed__() 方法並不常用。它以一個現有序列為引數,並將該序列中所有元素從尾到頭以逆序排列生成一個新的迭代器。

計算屬性

序號 目的 所編寫程式碼 Python 實際呼叫
獲取一個計算屬性(無條件的) x.my_property x.__getattribute__('my_property')
獲取一個計算屬性(後備) x.my_property x.__getattr__('my_property')
設定某屬性 x.my_property = value x.__setattr__('my_property',value)
刪除某屬性 del x.my_property x.__delattr__('my_property')
列出所有屬性和方法 dir(x) x.__dir__()
  • 如果某個類定義了 __getattribute__() 方法,在 每次引用屬性或方法名稱時 Python 都呼叫它(特殊方法名稱除外,因為那樣將會導致討厭的無限迴圈)。
  • 如果某個類定義了 __getattr__() 方法,Python 將只在正常的位置查詢屬性時才會呼叫它。如果例項 x 定義了屬性color, x.color 將 不會 呼叫x.__getattr__('color');而只會返回x.color 已定義好的值。
  • 無論何時給屬性賦值,都會呼叫__setattr__()方法。
  • 無論何時刪除一個屬性,都將呼叫 __delattr__() 方法。
  • 如果定義了 __getattr__() __getattribute__() 方法,__dir__()方法將非常有用。通常,呼叫 dir(x) 將只顯示正常的屬性和方法。如果__getattr()__方法動態處理color 屬性, dir(x) 將不會將 color 列為可用屬性。可透過覆蓋 __dir__() 方法允許將 color 列為可用屬性,對於想使用你的類但卻不想深入其內部的人來說,該方法非常有益。
序號 目的 所編寫程式碼 Python 實際呼叫
序列的長度 len(seq) seq.__len__()
瞭解某序列是否包含特定的值 x in seq seq.__contains__(x)
序號 目的 所編寫程式碼 Python 實際呼叫
透過鍵來獲取值 x[key] x.__getitem__(key)
透過鍵來設定值 x[key] = value x.__setitem__(key,value)
刪除一個鍵值對 del x[key] x.__delitem__(key)
為缺失鍵提供預設值 x[nonexistent_key] x.__missing__(nonexistent_key)

可比較的類

我將此內容從前一節中拿出來使其單獨成節,是因為“比較”操作並不侷限於數字。許多資料型別都可以進行比較——字串、列表,甚至字典。如果要建立自己的類,且物件之間的比較有意義,可以使用下面的特殊方法來實現比較。

序號 目的 所編寫程式碼 Python 實際呼叫
相等 x == y x.__eq__(y)
不相等 x != y x.__ne__(y)
小於 x < y x.__lt__(y)
小於或等於 x <= y x.__le__(y)
大於 x > y x.__gt__(y)
大於或等於 x >= y x.__ge__(y)
布林上上下文環境中的真值 if x: x.__bool__()

可序列化的類

Python 支援 任意物件的序列化和反序列化。(多數 Python 參考資料稱該過程為 “pickling” 和 “unpickling”)。該技術對與將狀態儲存為檔案並在稍後恢復它非常有意義。所有的 內建資料型別 均已支援 pickling 。如果建立了自定義類,且希望它能夠 pickle,閱讀 pickle 協議 瞭解下列特殊方法何時以及如何被呼叫。

序號 目的 所編寫程式碼 Python 實際呼叫
自定義物件的複製 copy.copy(x) x.__copy__()
自定義物件的深度複製 copy.deepcopy(x) x.__deepcopy__()
在 pickling 之前獲取物件的狀態 pickle.dump(x, file) x.__getstate__()
序列化某物件 pickle.dump(x, file) x.__reduce__()
序列化某物件(新 pickling 協議) pickle.dump(x, file, protocol_version) x.__reduce_ex__(protocol_version)
控制 unpickling 過程中物件的建立方式 x = pickle.load(file) x.__getnewargs__()
在 unpickling 之後還原物件的狀態 x = pickle.load(file) x.__setstate__()

要重建序列化物件,Python 需要建立一個和被序列化的物件看起來一樣的新物件,然後設定新物件的所有屬性。__getnewargs__() 方法控制新物件的建立過程,而__setstate__()方法控制屬性值的還原方式。

可在 with 語塊中使用的類

with 語塊定義了 執行時刻上下文環境;在執行 with 語句時將“進入”該上下文環境,而執行該語塊中的最後一條語句將“退出”該上下文環境。

序號 目的 所編寫程式碼 Python 實際呼叫
在進入 with 語塊時進行一些特別操作 with x: x.__enter__()
在退出 with 語塊時進行一些特別操作 with x: x.__exit__()

該檔案物件同時定義了一個 __enter__() 和一個 __exit__() 方法。該 __enter__() 方法檢查檔案是否處於開啟狀態;如果沒有, _checkClosed()方法引發一個例外。
__enter__() 方法將始終返回 self —— 這是 with 語塊將用於呼叫屬性和方法的物件
在 with 語塊結束後,檔案物件將自動關閉。怎麼做到的?在__exit__()方法中呼叫了 self.close() .

__exit__()方法將總是被呼叫,哪怕是在 with 語塊中引發了例外。實際上,如果引發了例外,該例外資訊將會被傳遞給 __exit__() 方法。

相關文章