Python 用下劃線做爲變量前綴和後綴指定特殊變量html
_xxx 不能用’from module import *’導入python
__xxx__ 系統定義名字程序員
__xxx 類中的私有變量名數組
核心風格:避免用下劃線做爲變量名的開始。ssh
由於下劃線對解釋器有特殊的意義,並且是內建標識符所使用的符號,咱們建議程序員避免用下劃線做爲變量名的開始。通常來說,變量名_xxx被看做是「私有 的」,在模塊或類外不可使用。當變量是私有的時候,用_xxx 來表示變量是很好的習慣。由於變量名__xxx__對Python 來講有特殊含義,對於普通的變量應當避免這種命名風格。函數
「單下劃線」 開始的成員變量叫作保護變量,意思是隻有類對象和子類對象本身能訪問到這些變量;
「雙下劃線」 開始的是私有成員,意思是隻有類對象本身能訪問,連子類對象也不能訪問到這個數據。post
以單下劃線開頭(_foo)的表明不能直接訪問的類屬性,需經過類提供的接口進行訪問,不能用「from xxx import *」而導入;以雙下劃線開頭的(__foo)表明類的私有成員;以雙下劃線開頭和結尾的(__foo__)表明python裏特殊方法專用的標識,如 __init__()表明類的構造函數。url
如今咱們來總結下全部的系統定義屬性和方法, 先來看下保留屬性:.net
>>> 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}
接下來是保留方法,能夠把保留方法分類:
序號 | 目的 | 所編寫代碼 | 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) |
我將此內容從前一節中拿出來使其單獨成節,是由於「比較」操做並不侷限於數字。許多數據類型均可以進行比較——字符串、列表,甚至字典。若是要建立本身的類,且對象之間的比較有意義,可使用下面的特殊方法來實現比較。code
序號 | 目的 | 所編寫代碼 | 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__() |
如下是 with file
習慣用法 的運做方式:
# excerpt from io.py: def _checkClosed(self, msg=None): '''Internal: raise an ValueError if file is closed ''' if self.closed: raise ValueError('I/O operation on closed file.' if msg is None else msg) def __enter__(self): '''Context management protocol. Returns self.''' self._checkClosed() ① return self ② def __exit__(self, *args): '''Context management protocol. Calls close()''' self.close() ③
__enter__()
和一個 __exit__()
方法。該 __enter__()
方法檢查文件是否處於打開狀態;若是沒有, _checkClosed()
方法引起一個例外。__enter__()
方法將始終返回 self —— 這是 with
語塊將用於調用屬性和方法的對象with
語塊結束後,文件對象將自動關閉。怎麼作到的?在 __exit__()
方法中調用了self.close()
.
?該
__exit__()
方法將老是被調用,哪怕是在with
語塊中引起了例外。實際上,若是引起了例外,該例外信息將會被傳遞給__exit__()
方法。查閱 With 狀態上下文環境管理器 瞭解更多細節。
真正神奇的東西
若是知道本身在幹什麼,你幾乎能夠徹底控制類是如何比較的、屬性如何定義,以及類的子類是何種類型。
序號 | 目的 | 所編寫代碼 | Python 實際調用 |
---|---|---|---|
類構造器 | x = MyClass() |
x.__new__() |
|
* | 類析構器 | del x |
x.__del__() |
只定義特定集合的某些屬性 | x.__slots__() |
||
自定義散列值 | hash(x) |
x.__hash__() |
|
獲取某個屬性的值 | x.color |
type(x).__dict__['color'].__get__(x, type(x)) |
|
設置某個屬性的值 | x.color = 'PapayaWhip' |
type(x).__dict__['color'].__set__(x, 'PapayaWhip') |
|
刪除某個屬性 | del x.color |
type(x).__dict__['color'].__del__(x) |
|
控制某個對象是不是該對象的實例 your class | isinstance(x, MyClass) |
MyClass.__instancecheck__(x) |
|
控制某個類是不是該類的子類 | issubclass(C, MyClass) |
MyClass.__subclasscheck__(C) |
|
控制某個類是不是該抽象基類的子類 | issubclass(C, MyABC) |
MyABC.__subclasshook__(C) |
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有意義時會調用