python python中那些雙下划線開頭的那些函數都是干啥用用的


1.寫在前面

今天遇到了__slots__,,所以我就想了解下python中那些雙下划線開頭的那些函數都是干啥用用的,翻到了下面這篇博客,看着很全面,我只了解其中的一部分,還不敢亂下定義。

 其實如果足夠了解一些知識,知道自己想要什么,就可以根據這些變量,函數等的特性訂制出很高效的類。這才是我們學習的目的。

 

2.小概況一下

python用下划線作為變量前綴和后綴指定特殊變量

_xxx 不能用’from module import *’導入

__xxx__ 系統定義名字

__xxx 類中的私有變量名

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

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

“單下划線” 開始的成員變量叫做保護變量,意思是只有類對象和子類對象自己能訪問到這些變量;
“雙下划線” 開始的是私有成員,意思是只有類對象自己能訪問,連子類對象也不能訪問到這個數據。

以單下划線開頭(_foo)的代表不能直接訪問的類屬性,需通過類提供的接口進行訪問,不能用“from xxx import *”而導入;以雙下划線開頭的(__foo)代表類的私有成員;以雙下划線開頭和結尾的(__foo__)代表python里特殊方法專用的標識,如 __init__()代表類的構造函數。

 

 

 3.保留屬性:

 先來看下保留屬性:

>>> Class1.__doc__ # 類型幫助信息 'Class1 Doc.' 
>>> Class1.__name__ # 類型名稱 'Class1'
>>> Class1.__module__ # 類型所在模塊 '__main__'
>>> Class1.__bases__ # 類型所繼承的基類 (<type 'object'>,)
>>> Class1.__dict__ # 類型字典,存儲所有類型成員信息。 <dictproxy object at 0x00D3AD70>
>>> Class1().__class__ # 類型 <class '__main__.Class1'>
>>> Class1().__module__ # 實例類型所在模塊 '__main__'
>>> Class1().__dict__ # 對象字典,存儲所有實例成員信息。 {'i': 1234}






4.保留方法,

可以把保留方法分類:

 

 
        
  1. 對 __init__() 方法的調用發生在實例被創建 之后 。如果要控制實際創建進程,請使用 __new__() 方法
  2. 按照約定, __repr__() 方法所返回的字符串為合法的 Python 表達式。
  3. 在調用 print(x) 的同時也調用了 __str__() 方法。
  4. 由於 bytes 類型的引入而從 Python 3 開始出現

 

 

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

  1. 無論何時創建迭代器都將調用 __iter__() 方法。這是用初始值對迭代器進行初始化的絕佳之處。
  2. 無論何時從迭代器中獲取下一個值都將調用 __next__() 方法。
  3. __reversed__() 方法並不常用。它以一個現有序列為參數,並將該序列中所有元素從尾到頭以逆序排列生成一個新的迭代器。

 

 

 

 6.計算屬性

 

 

  1. 如果某個類定義了 __getattribute__() 方法,在 每次引用屬性或方法名稱時 Python 都調用它(特殊方法名稱除外,因為那樣將會導致討厭的無限循環)。
  2. 如果某個類定義了 __getattr__() 方法,Python 將只在正常的位置查詢屬性時才會調用它。如果實例 x 定義了屬性color, x.color 將 不會 調用x.__getattr__('color');而只會返回x.color 已定義好的值。
  3. 無論何時給屬性賦值,都會調用 __setattr__() 方法。
  4. 無論何時刪除一個屬性,都將調用 __delattr__() 方法。
  5. 如果定義了 __getattr__() 或 __getattribute__() 方法, __dir__() 方法將非常有用。通常,調用 dir(x) 將只顯示正常的屬性和方法。如果__getattr()__方法動態處理color 屬性, dir(x) 將不會將 color 列為可用屬性。可通過覆蓋 __dir__() 方法允許將 color 列為可用屬性,對於想使用你的類但卻不想深入其內部的人來說,該方法非常有益。

 

 

 

7.可比較的類

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

 

 

 

 

8.可序列化的類

Python 支持 任意對象的序列化和反序列化。(多數 Python 參考資料稱該過程為 “pickling” 和 “unpickling”)。該技術對與將狀態保存為文件並在稍后恢復它非常有意義。所有的 內置數據類型 均已支持 pickling 。如果創建了自定義類,且希望它能夠 pickle,閱讀 pickle 協議 了解下列特殊方法何時以及如何被調用

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

 

 

 

9.可在 with 語塊中使用的類

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

  1. 該文件對象同時定義了一個 __enter__() 和一個 __exit__() 方法。該 __enter__() 方法檢查文件是否處於打開狀態;如果沒有, _checkClosed()方法引發一個例外。
  2. __enter__() 方法將始終返回 self —— 這是 with 語塊將用於調用屬性和方法的對象
  3. 在 with 語塊結束后,文件對象將自動關閉。怎么做到的?在 __exit__() 方法中調用了 self.close() .

 

 

10.真正神奇的東西

 如果知道自己在干什么,你幾乎可以完全控制類是如何比較的、屬性如何定義,以及類的子類是何種類型

python中以雙下划線的是一些系統定義得名稱,讓python以更優雅得語法實行一些操作,本質上還是一些函數和變量,與其他函數和變量無二。
比如x.__add__(y) 等價於 x+y
有一些很常見,有一些可能比較偏,在這里羅列一下,做個筆記,備忘。
x.__contains__(y) 等價於 y in x, 在list,str, dict,set等容器中有這個函數
__base__, __bases__, __mro__, 關於類繼承和函數查找路徑的。
class.__subclasses__(), 返回子類列表
x.__call__(...) == x(...)
x.__cmp__(y) == cmp(x,y)
x.__getattribute__('name') == x.name == getattr(x, 'name'),  比__getattr__更早調用
x.__hash__() == hash(x)
x.__sizeof__(), x在內存中的字節數, x為class得話, 就應該是x.__basicsize__
x.__delattr__('name') == del x.name
__dictoffset__ attribute tells you the offset to where you find the pointer to the __dict__ object in any instance object that has one. It is in bytes.
__flags__, 返回一串數字,用來判斷該類型能否被序列化(if it's a heap type), __flags__ & 512
S.__format__, 有些類有用
x.__getitem__(y) == x[y], 相應還有__setitem__, 某些不可修改類型如set,str沒有__setitem__
x.__getslice__(i, j) == x[i:j], 有個疑問,x='123456789', x[::2],是咋實現得
__subclasscheck__(), check if a class is subclass
__instancecheck__(), check if an object is an instance
__itemsize__, These fields allow calculating the size in bytes of instances of the type. 0是可變長度, 非0則是固定長度
x.__mod__(y) == x%y, x.__rmod__(y) == y%x
x.__module__ , x所屬模塊
x.__mul__(y) == x*y,  x.__rmul__(y) == y*x

__reduce__, __reduce_ex__ , for pickle

__slots__ 使用之后類變成靜態一樣,沒有了__dict__, 實例也不可新添加屬性

__getattr__ 在一般的查找屬性查找不到之后會調用此函數

__setattr__ 取代一般的賦值操作,如果有此函數會調用此函數, 如想調用正常賦值途徑用 object.__setattr__(self, name, value)

__delattr__ 同__setattr__, 在del obj.name有意義時會調用

 

 

 

 

 

轉摘自https://www.cnblogs.com/nkwy2012/p/6264031.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM