Python的特殊成员
Python 用下劃線作為變量前綴和后綴指定特殊變量
_xxx 不能用’from module import *’導入
__xxx__ 系統定義名字
__xxx 類中的私有變量名
核心風格:避免用下劃線作為變量名的開始。
現在我們來總結下所有的系統定義屬性和方法, 先來看下保留屬性:
>>> 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}接下來是保留方法,可以把保留方法分類:
類的基礎方法
行為方式與迭代器類似的類
計算屬性
行為方式與函數類似的類
行為方式與序列類似的類
行為方式與字典類似的類
可比較的類
可序列化的類
可在 with 語塊中使用的類
真正神奇的東西
類的基礎方法
| 初始化一個實例 | x = MyClass() | x.__init__() |
| 字符串的“官方”表現形式 | repr(x) | x.__repr__() |
| 字符串的“非正式”值 | str(x) | x.__str__() |
| 字節數組的“非正式”值 | bytes(x) | x.__bytes__() |
| 格式化字符串的值 | format(x, format_spec) | x.__format__(format_spec) |
?
行為方式與迭代器類似的類
| 遍歷某個序列 | iter(seq) | seq.__iter__() |
| 從迭代器中獲取下一個值 | next(seq) | seq.__next__() |
| 按逆序創建一個迭代器 | reversed(seq) | seq.__reversed__() |
?
計算屬性
| 獲取一個計算屬性(無條件的) | 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__() |
?
行為方式與函數類似的類
可以讓類的實例變得可調用——就像函數可以調用一樣——通過定義 __call__() 方法。
| 像調用函數一樣“調用”一個實例 | my_instance() | my_instance.__call__() |
zipfile 模塊 通過該方式定義了一個可以使用給定密碼解密 經加密 zip 文件的類。該 zip解密 算法需要在解密的過程中保存狀態。通過將解密器定義為類,使我們得以在 decryptor 類的單個實例中對該狀態進行維護。狀態在__init__() 方法中進行初始化,如果文件經加密 則進行更新。但由于該類像函數一樣“可調用”,因此可以將實例作為map() 函數的第一個參數傳入,代碼如下:
# excerpt from zipfile.py class _ZipDecrypter: def __init__(self, pwd): self.key0 = 305419896 self.key1 = 591751049 self.key2 = 878082192 for p in pwd: self._UpdateKeys(p) def __call__(self, c): assert isinstance(c, int) k = self.key2 | 2 c = c ^ (((k * (k^1)) >> & 255) self._UpdateKeys(c) return c zd = _ZipDecrypter(pwd) bytes = zef_file.read(12) h = list(map(zd, bytes[0:12]))?
?
行為方式與序列類似的類
如果類作為一系列值的容器出現——也就是說如果對某個類來說,是否“包含”某值是件有意義的事情——那么它也許應該定義下面的特殊方法已,讓它的行為方式與序列類似。
| 序列的長度 | len(seq) | seq.__len__() |
| 了解某序列是否包含特定的值 | x in seq | seq.__contains__(x) |
cgi 模塊 在其FieldStorage 類中使用了這些方法,該類用于表示提交給動態網頁的所有表單字段或查詢參數。
# A script which responds to http://example.com/search?q=cgi import cgi fs = cgi.FieldStorage() if 'q' in fs: do_search() # An excerpt from cgi.py that explains how that works class FieldStorage: . . . def __contains__(self, key): if self.list is None: raise TypeError('not indexable') return any(item.name == key for item in self.list) def __len__(self): return len(self.keys())?
一旦創建了 cgi.FieldStorage 類的實例,就可以使用 “in” 運算符來檢查查詢字符串中是否包含了某個特定參數。?
行為方式與字典類似的類
在前一節的基礎上稍作拓展,就不僅可以對 “in” 運算符和 len() 函數進行響應,還可像全功能字典一樣根據鍵來返回值。
| 通過鍵來獲取值 | 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) |
cgi 模塊 的FieldStorage 類 同樣定義了這些特殊方法,也就是說可以像下面這樣編碼:
# A script which responds to http://example.com/search?q=cgi import cgi fs = cgi.FieldStorage() if 'q' in fs: do_search(fs['q']) # An excerpt from cgi.py that shows how it works class FieldStorage: . . . def __getitem__(self, key): if self.list is None: raise TypeError('not indexable') found = [] for item in self.list: if item.name == key: found.append(item) if not found: raise KeyError(key) if len(found) == 1:return found[0] else: return found?
?
可比較的類
我將此內容從前一節中拿出來使其單獨成節,是因為“比較”操作并不局限于數字。許多數據類型都可以進行比較——字符串、列表,甚至字典。如果要創建自己的類,且對象之間的比較有意義,可以使用下面的特殊方法來實現比較。
| 相等 | 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__() |
?如果定義了 __lt__() 方法但沒有定義 __gt__() 方法,Python 將通過經交換的算子調用__lt__() 方法。然而,Python 并不會組合方法。例如,如果定義了__lt__() 方法和__eq()__ 方法,并試圖測試是否 x <= y,Python 不會按順序調用__lt__() 和__eq()__ 。它將只調用__le__() 方法。
可序列化的類
Python 支持 任意對象的序列化和反序列化。(多數 Python 參考資料稱該過程為 “pickling” 和 “unpickling”)。該技術對與將狀態保存為文件并在稍后恢復它非常有意義。所有的內置數據類型 均已支持 pickling 。如果創建了自定義類,且希望它能夠 pickle,閱讀pickle 協議 了解下列特殊方法何時以及如何被調用。
| 自定義對象的復制 | 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 語句時將“進入”該上下文環境,而執行該語塊中的最后一條語句將“退出”該上下文環境。
| 在進入 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()?
?該 __exit__() 方法將總是被調用,哪怕是在 with 語塊中引發了例外。實際上,如果引發了例外,該例外信息將會被傳遞給__exit__() 方法。查閱With 狀態上下文環境管理器 了解更多細節。
真正神奇的東西
如果知道自己在干什么,你幾乎可以完全控制類是如何比較的、屬性如何定義,以及類的子類是何種類型。
| 類構造器 | 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) |
轉載于:https://www.cnblogs.com/charles7987/p/9999617.html
總結
以上是生活随笔為你收集整理的Python的特殊成员的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 美国最受欢迎的量化交易模型有哪些吗?
- 下一篇: ElasticJob‐Lite:自定义作