日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

Python的特殊成员

發(fā)布時間:2023/12/10 python 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python的特殊成员 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Python 用下劃線作為變量前綴和后綴指定特殊變量

_xxx 不能用’from module import *’導(dǎo)入

__xxx__ 系統(tǒng)定義名字

__xxx 類中的私有變量名

核心風(fēng)格:避免用下劃線作為變量名的開始。

現(xiàn)在我們來總結(jié)下所有的系統(tǒng)定義屬性和方法, 先來看下保留屬性:

>>> 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}

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

  類的基礎(chǔ)方法

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

  計算屬性

  行為方式與函數(shù)類似的類

  行為方式與序列類似的類

  行為方式與字典類似的類

  可比較的類

  可序列化的類

  可在 with 語塊中使用的類

  真正神奇的東西

類的基礎(chǔ)方法

序號目的所編寫代碼Python 實際調(diào)用①②③④⑤
初始化一個實例x = MyClass()x.__init__()
字符串的“官方”表現(xiàn)形式repr(x)x.__repr__()
字符串的“非正式”值str(x)x.__str__()
字節(jié)數(shù)組的“非正式”值bytes(x)x.__bytes__()
格式化字符串的值format(x, format_spec)x.__format__(format_spec)
  • 對 __init__() 方法的調(diào)用發(fā)生在實例被創(chuàng)建 之后 。如果要控制實際創(chuàng)建進程,請使用 __new__() 方法。
  • 按照約定, __repr__()方法所返回的字符串為合法的 Python 表達式。
  • 在調(diào)用 print(x) 的同時也調(diào)用了 __str__()方法。
  • 由于 bytes 類型的引入而從 Python 3 開始出現(xiàn)。
  • ?

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

    序號目的所編寫代碼Python 實際調(diào)用①②③
    遍歷某個序列iter(seq)seq.__iter__()
    從迭代器中獲取下一個值next(seq)seq.__next__()
    按逆序創(chuàng)建一個迭代器reversed(seq)seq.__reversed__()
  • 無論何時創(chuàng)建迭代器都將調(diào)用 __iter__()方法。這是用初始值對迭代器進行初始化的絕佳之處。
  • 無論何時從迭代器中獲取下一個值都將調(diào)用 __next__()方法。
  • __reversed__() 方法并不常用。它以一個現(xiàn)有序列為參數(shù),并將該序列中所有元素從尾到頭以逆序排列生成一個新的迭代器。
  • ?

    計算屬性

    序號目的所編寫代碼Python 實際調(diào)用①②③④⑤
    獲取一個計算屬性(無條件的)x.my_propertyx.__getattribute__('my_property')
    獲取一個計算屬性(后備)x.my_propertyx.__getattr__('my_property')
    設(shè)置某屬性x.my_property = valuex.__setattr__('my_property',value)
    刪除某屬性del x.my_propertyx.__delattr__('my_property')
    列出所有屬性和方法dir(x)x.__dir__()
  • 如果某個類定義了 __getattribute__() 方法,在 每次引用屬性或方法名稱時Python 都調(diào)用它(特殊方法名稱除外,因為那樣將會導(dǎo)致討厭的無限循環(huán))。
  • 如果某個類定義了 __getattr__() 方法,Python 將只在正常的位置查詢屬性時才會調(diào)用它。如果實例 x 定義了屬性color,x.color 將不會 調(diào)用x.__getattr__('color');而只會返回x.color已定義好的值。
  • 無論何時給屬性賦值,都會調(diào)用 __setattr__()方法。
  • 無論何時刪除一個屬性,都將調(diào)用 __delattr__()方法。
  • 如果定義了 __getattr__() 或 __getattribute__() 方法, __dir__() 方法將非常有用。通常,調(diào)用 dir(x) 將只顯示正常的屬性和方法。如果 __getattr()__方法動態(tài)處理color 屬性,dir(x) 將不會將color 列為可用屬性。可通過覆蓋 __dir__() 方法允許將color 列為可用屬性,對于想使用你的類但卻不想深入其內(nèi)部的人來說,該方法非常有益。
  • ?

    行為方式與函數(shù)類似的類

    可以讓類的實例變得可調(diào)用——就像函數(shù)可以調(diào)用一樣——通過定義 __call__() 方法。

    序號目的所編寫代碼Python 實際調(diào)用①
    像調(diào)用函數(shù)一樣“調(diào)用”一個實例my_instance()my_instance.__call__()

    zipfile 模塊 通過該方式定義了一個可以使用給定密碼解密 經(jīng)加密 zip 文件的類。該 zip解密 算法需要在解密的過程中保存狀態(tài)。通過將解密器定義為類,使我們得以在 decryptor 類的單個實例中對該狀態(tài)進行維護。狀態(tài)在__init__() 方法中進行初始化,如果文件經(jīng)加密 則進行更新。但由于該類像函數(shù)一樣“可調(diào)用”,因此可以將實例作為map() 函數(shù)的第一個參數(shù)傳入,代碼如下:

    # 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]))

    ?

  • _ZipDecryptor 類維護了以三個旋轉(zhuǎn)密鑰形式出現(xiàn)的狀態(tài),該狀態(tài)稍后將在 _UpdateKeys()方法中更新(此處未展示)。
  • 該類定義了一個 __call__() 方法,使得該類可像函數(shù)一樣調(diào)用。在此例中,__call__()對 zip 文件的單個字節(jié)進行解密,然后基于經(jīng)解密的字節(jié)對旋轉(zhuǎn)密碼進行更新。
  • zd 是 _ZipDecryptor 類的一個實例。變量 pwd 被傳入 __init__()方法,并在其中被存儲和用于首次旋轉(zhuǎn)密碼更新。
  • 給出 zip 文件的頭 12 個字節(jié),將這些字節(jié)映射給 zd 進行解密,實際上這將導(dǎo)致調(diào)用 __call__() 方法 12 次,也就是 更新內(nèi)部狀態(tài)并返回結(jié)果字節(jié) 12 次。
  • ?

    行為方式與序列類似的類

    如果類作為一系列值的容器出現(xiàn)——也就是說如果對某個類來說,是否“包含”某值是件有意義的事情——那么它也許應(yīng)該定義下面的特殊方法已,讓它的行為方式與序列類似。

    序號目的所編寫代碼Python 實際調(diào)用①②
    序列的長度len(seq)seq.__len__()
    了解某序列是否包含特定的值x in seqseq.__contains__(x)

    cgi 模塊 在其FieldStorage 類中使用了這些方法,該類用于表示提交給動態(tài)網(wǎng)頁的所有表單字段或查詢參數(shù)。

    # 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())

    ?

    一旦創(chuàng)建了 cgi.FieldStorage 類的實例,就可以使用 “in” 運算符來檢查查詢字符串中是否包含了某個特定參數(shù)。
  • 而 __contains__()方法是令該魔法生效的主角。
  • 如果代碼為 if 'q' in fs,Python 將在 fs 對象中查找 __contains__() 方法,而該方法在cgi.py 中已經(jīng)定義。'q' 的值被當(dāng)作key 參數(shù)傳入__contains__()方法。
  • 同樣的 FieldStorage 類還支持返回其長度,因此可以編寫代碼 len(fs) 而其將調(diào)用FieldStorage 的__len__()方法,并返回其識別的查詢參數(shù)個數(shù)。
  • self.keys() 方法檢查 self.list is None 是否為真值,因此 __len__ 方法無需重復(fù)該錯誤檢查。
  • ?

    行為方式與字典類似的類

    在前一節(jié)的基礎(chǔ)上稍作拓展,就不僅可以對 “in” 運算符和 len() 函數(shù)進行響應(yīng),還可像全功能字典一樣根據(jù)鍵來返回值。

    序號目的所編寫代碼Python 實際調(diào)用①②③④
    通過鍵來獲取值x[key]x.__getitem__(key)
    通過鍵來設(shè)置值x[key] = valuex.__setitem__(key, value)
    刪除一個鍵值對del x[key]x.__delitem__(key)
    為缺失鍵提供默認(rèn)值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

    ?

  • fs 對象是 cgi.FieldStorage 類的一個實例,但仍然可以像 fs['q']這樣估算表達式。
  • fs['q'] 將 key 參數(shù)設(shè)置為 'q' 來調(diào)用 __getitem__() 方法。然后它將在其內(nèi)部維護的查詢參數(shù)列表 (self.list) 中查找一個.name 與給定鍵相符的字典項。
  • ?

    可比較的類

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

    序號目的所編寫代碼Python 實際調(diào)用①②③④⑤⑥⑦
    相等x == yx.__eq__(y)
    不相等x != yx.__ne__(y)
    小于x < yx.__lt__(y)
    小于或等于x <= yx.__le__(y)
    大于x > yx.__gt__(y)
    大于或等于x >= yx.__ge__(y)
    布爾上上下文環(huán)境中的真值if x:x.__bool__()

    ?如果定義了 __lt__() 方法但沒有定義 __gt__() 方法,Python 將通過經(jīng)交換的算子調(diào)用__lt__() 方法。然而,Python 并不會組合方法。例如,如果定義了__lt__() 方法和__eq()__ 方法,并試圖測試是否 x <= y,Python 不會按順序調(diào)用__lt__() 和__eq()__ 。它將只調(diào)用__le__() 方法。

    可序列化的類

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

    序號目的所編寫代碼Python 實際調(diào)用①②③④⑤⑥⑦
    自定義對象的復(fù)制copy.copy(x)x.__copy__()
    自定義對象的深度復(fù)制copy.deepcopy(x)x.__deepcopy__()
    在 pickling 之前獲取對象的狀態(tài)pickle.dump(x, file)x.__getstate__()
    序列化某對象pickle.dump(x, file)x.__reduce__()
    序列化某對象(新 pickling 協(xié)議)pickle.dump(x, file, protocol_version)x.__reduce_ex__(protocol_version)
    控制 unpickling 過程中對象的創(chuàng)建方式x = pickle.load(file)x.__getnewargs__()
    在 unpickling 之后還原對象的狀態(tài)x = pickle.load(file)x.__setstate__()

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

    可在 with 語塊中使用的類

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

    序號目的所編寫代碼Python 實際調(diào)用①②
    在進入 with 語塊時進行一些特別操作with x:x.__enter__()
    在退出 with 語塊時進行一些特別操作with x:x.__exit__()

    以下是 with file 習(xí)慣用法 的運作方式:

    # 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__() 方法檢查文件是否處于打開狀態(tài);如果沒有, _checkClosed()方法引發(fā)一個例外。
  • __enter__() 方法將始終返回 self —— 這是 with語塊將用于調(diào)用屬性和方法的對象
  • 在 with 語塊結(jié)束后,文件對象將自動關(guān)閉。怎么做到的?在 __exit__() 方法中調(diào)用了 self.close() .
  • ?該 __exit__() 方法將總是被調(diào)用,哪怕是在 with 語塊中引發(fā)了例外。實際上,如果引發(fā)了例外,該例外信息將會被傳遞給__exit__() 方法。查閱With 狀態(tài)上下文環(huán)境管理器 了解更多細(xì)節(jié)。

    真正神奇的東西

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

    序號目的所編寫代碼Python 實際調(diào)用①②③④⑤⑥⑦⑧⑨⑩
    類構(gòu)造器x = MyClass()x.__new__()
    類析構(gòu)器del xx.__del__()
    只定義特定集合的某些屬性?x.__slots__()
    自定義散列值hash(x)x.__hash__()
    獲取某個屬性的值x.colortype(x).__dict__['color'].__get__(x, type(x))
    設(shè)置某個屬性的值x.color = 'PapayaWhip'type(x).__dict__['color'].__set__(x, 'PapayaWhip')
    刪除某個屬性del x.colortype(x).__dict__['color'].__del__(x)
    控制某個對象是否是該對象的實例 your classisinstance(x, MyClass)MyClass.__instancecheck__(x)
    控制某個類是否是該類的子類issubclass(C, MyClass)MyClass.__subclasscheck__(C)
    控制某個類是否是該抽象基類的子類issubclass(C, MyABC)MyABC.__subclasshook__(C)

    轉(zhuǎn)載于:https://www.cnblogs.com/charles7987/p/9999617.html

    總結(jié)

    以上是生活随笔為你收集整理的Python的特殊成员的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。