溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

python下劃線的示例分析

發(fā)布時(shí)間:2021-02-23 10:46:26 來(lái)源:億速云 閱讀:190 作者:清風(fēng) 欄目:編程語(yǔ)言

這篇文章主要為大家展示了python下劃線的示例分析,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶大家一起來(lái)研究并學(xué)習(xí)一下“python下劃線的示例分析”這篇文章吧。

Python主要用來(lái)做什么

Python主要應(yīng)用于:1、Web開發(fā);2、數(shù)據(jù)科學(xué)研究;3、網(wǎng)絡(luò)爬蟲;4、嵌入式應(yīng)用開發(fā);5、游戲開發(fā);6、桌面應(yīng)用開發(fā)。

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

_xxx      不能用'from
module import *'
導(dǎo)入 
__xxx__
 系統(tǒng)定義名字 
__xxx
    類中的私有變量名 

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

因?yàn)橄聞澗€對(duì)解釋器有特殊的意義,而且是內(nèi)建標(biāo)識(shí)符所使用的符號(hào),我們建議程序員避免用下劃線作為變量名的開始。一般來(lái)講,變量名_xxx被看作是私有
,在模塊或類外不可以使用。當(dāng)變量是私有的時(shí)候,用_xxx 來(lái)表示變量是很好的習(xí)慣。因?yàn)樽兞棵?span lang="EN-US">__xxx__對(duì)Python 來(lái)說(shuō)有特殊含義,對(duì)于普通的變量應(yīng)當(dāng)避免這種命名風(fēng)格。

"單下劃線" 開始的成員變量叫做保護(hù)變量,意思是只有類對(duì)象和子類對(duì)象自己能訪問(wèn)到這些變量;
"
雙下劃線" 開始的是私有成員,意思是只有類對(duì)象自己能訪問(wèn),連子類對(duì)象也不能訪問(wèn)到這個(gè)數(shù)據(jù)。

以單下劃線開頭(_foo)的代表不能直接訪問(wèn)的類屬性,需通過(guò)類提供的接口進(jìn)行訪問(wèn),不能用from
xxx import *
而導(dǎo)入;以雙下劃線開頭的(__foo)代表類的私有成員;以雙下劃線開頭和結(jié)尾的(__foo__)代表python里特殊方法專用的標(biāo)識(shí),如 __init__()代表類的構(gòu)造函數(shù)。

 

結(jié)論:

1、_xxx     不能用于from
module import *
 以單下劃線開頭的表示的是protected類型的變量。即保護(hù)類型只能允許其本身與子類進(jìn)行訪問(wèn)。

2、__xxx    雙下劃線的表示的是私有類型的變量。只能是允許這個(gè)類本身進(jìn)行訪問(wèn)了。連子類也不可以

3、__xxx___定義的是特列方法。像__init__之類的

 

學(xué)習(xí)心得:

1、搞清楚了python 里面的單下劃線與雙下劃線的區(qū)別

source: http://blog.163.com/jackylau_v/blog/static/175754040201182113817834/

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

2011-09-02 23:38:17|  分類: 派森程序點(diǎn)滴|字號(hào) 訂閱

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

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

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

__xxx 類中的私有變量名

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

因?yàn)橄聞澗€對(duì)解釋器有特殊的意義,而且是內(nèi)建標(biāo)識(shí)符所使用的符號(hào),我們建議程序員避免用下劃線作為變量名的開始。一般來(lái)講,變量名_xxx被看作是“私有 的”,在模塊或類外不可以使用。當(dāng)變量是私有的時(shí)候,用_xxx 來(lái)表示變量是很好的習(xí)慣。因?yàn)樽兞棵鸰_xxx__對(duì)Python 來(lái)說(shuō)有特殊含義,對(duì)于普通的變量應(yīng)當(dāng)避免這種命名風(fēng)格。

“單下劃線” 開始的成員變量叫做保護(hù)變量,意思是只有類對(duì)象和子類對(duì)象自己能訪問(wèn)到這些變量;
“雙下劃線” 開始的是私有成員,意思是只有類對(duì)象自己能訪問(wèn),連子類對(duì)象也不能訪問(wèn)到這個(gè)數(shù)據(jù)。

以單下劃線開頭(_foo)的代表不能直接訪問(wèn)的類屬性,需通過(guò)類提供的接口進(jìn)行訪問(wèn),不能用“from xxx import *”而導(dǎo)入;以雙下劃線開頭的(__foo)代表類的私有成員;以雙下劃線開頭和結(jié)尾的(__foo__)代表python里特殊方法專用的標(biāo)識(shí),如 __init__()代表類的構(gòu)造函數(shù)。

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

>>> Class1.__doc__ # 類型幫助信息 'Class1 Doc.' >>> Class1.__name__ # 類型名稱 'Class1' >>> Class1.__module__ # 類型所在模塊 '__main__' >>> Class1.__bases__ # 類型所繼承的基類 (<type 'object'>,) >>> Class1.__dict__ # 類型字典,存儲(chǔ)所有類型成員信息。 <dictproxy object at 0x00D3AD70> >>> Class1().__class__ # 類型 <class '__main__.Class1'> >>> Class1().__module__ # 實(shí)例類型所在模塊 '__main__' >>> Class1().__dict__ # 對(duì)象字典,存儲(chǔ)所有實(shí)例成員信息。 {'i': 1234}
接下來(lái)是保留方法,可以把保留方法分類:

類的基礎(chǔ)方法

序號(hào)目的所編寫代碼Python 實(shí)際調(diào)用
初始化一個(gè)實(shí)例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)
  1. 對(duì) __init__() 方法的調(diào)用發(fā)生在實(shí)例被創(chuàng)建 之后 。如果要控制實(shí)際創(chuàng)建進(jìn)程,請(qǐng)使用 __new__() 方法。

  2. 按照約定, __repr__() 方法所返回的字符串為合法的 Python 表達(dá)式。

  3. 在調(diào)用 print(x) 的同時(shí)也調(diào)用了 __str__() 方法。

  4. 由于 bytes 類型的引入而從 Python 3 開始出現(xiàn)。

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

序號(hào)目的所編寫代碼Python 實(shí)際調(diào)用
遍歷某個(gè)序列iter(seq)seq.__iter__()
從迭代器中獲取下一個(gè)值next(seq)seq.__next__()
按逆序創(chuàng)建一個(gè)迭代器reversed(seq)seq.__reversed__()
  1. 無(wú)論何時(shí)創(chuàng)建迭代器都將調(diào)用 __iter__() 方法。這是用初始值對(duì)迭代器進(jìn)行初始化的絕佳之處。

  2. 無(wú)論何時(shí)從迭代器中獲取下一個(gè)值都將調(diào)用 __next__() 方法。

  3. __reversed__() 方法并不常用。它以一個(gè)現(xiàn)有序列為參數(shù),并將該序列中所有元素從尾到頭以逆序排列生成一個(gè)新的迭代器。

計(jì)算屬性
序號(hào)目的所編寫代碼Python 實(shí)際調(diào)用
獲取一個(gè)計(jì)算屬性(無(wú)條件的)x.my_propertyx.__getattribute__('my_property')
獲取一個(gè)計(jì)算屬性(后備)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__()
  1. 如果某個(gè)類定義了 __getattribute__() 方法,在 每次引用屬性或方法名稱時(shí) Python 都調(diào)用它(特殊方法名稱除外,因?yàn)槟菢訉?huì)導(dǎo)致討厭的無(wú)限循環(huán))。

  2. 如果某個(gè)類定義了 __getattr__() 方法,Python 將只在正常的位置查詢屬性時(shí)才會(huì)調(diào)用它。如果實(shí)例 x 定義了屬性 color, x.color 將 不會(huì) 調(diào)用x.__getattr__('color');而只會(huì)返回 x.color 已定義好的值。

  3. 無(wú)論何時(shí)給屬性賦值,都會(huì)調(diào)用 __setattr__() 方法。

  4. 無(wú)論何時(shí)刪除一個(gè)屬性,都將調(diào)用 __delattr__() 方法。

  5. 如果定義了 __getattr__() 或 __getattribute__() 方法, __dir__() 方法將非常有用。通常,調(diào)用 dir(x) 將只顯示正常的屬性和方法。如果 __getattr()__方法動(dòng)態(tài)處理 color 屬性, dir(x) 將不會(huì)將 color 列為可用屬性??赏ㄟ^(guò)覆蓋 __dir__() 方法允許將 color 列為可用屬性,對(duì)于想使用你的類但卻不想深入其內(nèi)部的人來(lái)說(shuō),該方法非常有益。

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

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

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

zipfile 模塊 通過(guò)該方式定義了一個(gè)可以使用給定密碼解密 經(jīng)加密 zip 文件的類。該 zip 解密 算法需要在解密的過(guò)程中保存狀態(tài)。通過(guò)將解密器定義為類,使我們得以在
decryptor 類的單個(gè)實(shí)例中對(duì)該狀態(tài)進(jìn)行維護(hù)。狀態(tài)在__init__() 方法中進(jìn)行初始化,如果文件 經(jīng)加密 則進(jìn)行更新。但由于該類像函數(shù)一樣“可調(diào)用”,因此可以將實(shí)例作為map() 函數(shù)的第一個(gè)參數(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]))             ④
  1. _ZipDecryptor 類維護(hù)了以三個(gè)旋轉(zhuǎn)密鑰形式出現(xiàn)的狀態(tài),該狀態(tài)稍后將在 _UpdateKeys() 方法中更新(此處未展示)。

  2. 該類定義了一個(gè) __call__() 方法,使得該類可像函數(shù)一樣調(diào)用。在此例中,__call__() 對(duì) zip 文件的單個(gè)字節(jié)進(jìn)行解密,然后基于經(jīng)解密的字節(jié)對(duì)旋轉(zhuǎn)密碼進(jìn)行更新。

  3. zd 是 _ZipDecryptor 類的一個(gè)實(shí)例。變量 pwd 被傳入 __init__() 方法,并在其中被存儲(chǔ)和用于首次旋轉(zhuǎn)密碼更新。

  4. 給出 zip 文件的頭 12 個(gè)字節(jié),將這些字節(jié)映射給 zd 進(jìn)行解密,實(shí)際上這將導(dǎo)致調(diào)用 __call__() 方法 12 次,也就是 更新內(nèi)部狀態(tài)并返回結(jié)果字節(jié) 12 次。

行為方式與序列類似的類

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

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

cgi 模塊 在其 FieldStorage 類中使用了這些方法,該類用于表示提交給動(dòng)態(tài)網(wǎng)頁(yè)的所有表單字段或查詢參數(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())                             ⑤
  1. 一旦創(chuàng)建了 cgi.FieldStorage 類的實(shí)例,就可以使用 “in” 運(yùn)算符來(lái)檢查查詢字符串中是否包含了某個(gè)特定參數(shù)。

  2. 而 __contains__() 方法是令該魔法生效的主角。

  3. 如果代碼為 if 'q' in fs,Python 將在 fs 對(duì)象中查找 __contains__() 方法,而該方法在 cgi.py 中已經(jīng)定義。'q' 的值被當(dāng)作 key 參數(shù)傳入__contains__() 方法。

  4. 同樣的 FieldStorage 類還支持返回其長(zhǎng)度,因此可以編寫代碼 len(fs) 而其將調(diào)用 FieldStorage 的 __len__()方法,并返回其識(shí)別的查詢參數(shù)個(gè)數(shù)。

  5. self.keys() 方法檢查 self.list is None 是否為真值,因此 __len__ 方法無(wú)需重復(fù)該錯(cuò)誤檢查。

行為方式與字典類似的類

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

序號(hào)目的所編寫代碼Python 實(shí)際調(diào)用
 通過(guò)鍵來(lái)獲取值x[key]x.__getitem__(key)
 通過(guò)鍵來(lái)設(shè)置值x[key] = valuex.__setitem__(keyvalue)
 刪除一個(gè)鍵值對(duì)del x[key]x.__delitem__(key)
 為缺失鍵提供默認(rèn)值x[nonexistent_key]x.__missing__(nonexistent_key)

cgi 模塊 的 FieldStorage 類 同樣定義了這些特殊方法,也就是說(shuō)可以像下面這樣編碼:

# 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
  1. fs 對(duì)象是 cgi.FieldStorage 類的一個(gè)實(shí)例,但仍然可以像 fs['q'] 這樣估算表達(dá)式。

  2. fs['q'] 將 key 參數(shù)設(shè)置為 'q' 來(lái)調(diào)用 __getitem__() 方法。然后它將在其內(nèi)部維護(hù)的查詢參數(shù)列表 (self.list) 中查找一個(gè) .name 與給定鍵相符的字典項(xiàng)。

可比較的類

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

序號(hào)目的所編寫代碼Python 實(shí)際調(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__() 方法但沒(méi)有定義 __gt__() 方法,Python 將通過(guò)經(jīng)交換的算子調(diào)用 __lt__() 方法。然而,Python 并不會(huì)組合方法。例如,如果定義了 __lt__() 方法和 __eq()__ 方法,并試圖測(cè)試是否 x <= y,Python 不會(huì)按順序調(diào)用 __lt__() 和 __eq()__ 。它將只調(diào)用__le__() 方法。

可序列化的類

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

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

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

可在 with 語(yǔ)塊中使用的類

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

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

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

# 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()                                       ③
  1. 該文件對(duì)象同時(shí)定義了一個(gè) __enter__() 和一個(gè) __exit__() 方法。該 __enter__() 方法檢查文件是否處于打開狀態(tài);如果沒(méi)有, _checkClosed() 方法引發(fā)一個(gè)例外。

  2. __enter__() 方法將始終返回 self —— 這是 with 語(yǔ)塊將用于調(diào)用屬性和方法的對(duì)象

  3. 在 with 語(yǔ)塊結(jié)束后,文件對(duì)象將自動(dòng)關(guān)閉。怎么做到的?在 __exit__() 方法中調(diào)用了 self.close() .

?該 __exit__() 方法將總是被調(diào)用,哪怕是在 with 語(yǔ)塊中引發(fā)了例外。實(shí)際上,如果引發(fā)了例外,該例外信息將會(huì)被傳遞給 __exit__() 方法。查閱 With
狀態(tài)上下文環(huán)境管理器 了解更多細(xì)節(jié)。

真正神奇的東西

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

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

以上就是關(guān)于“python下劃線的示例分析”的內(nèi)容,如果改文章對(duì)你有所幫助并覺(jué)得寫得不錯(cuò),勞請(qǐng)分享給你的好友一起學(xué)習(xí)新知識(shí),若想了解更多相關(guān)知識(shí)內(nèi)容,請(qǐng)多多關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI