新聞中心
3. 數(shù)據(jù)模型
3.1. 對(duì)象、值與類型
對(duì)象 是 python 中對(duì)數(shù)據(jù)的抽象。 Python 程序中的所有數(shù)據(jù)都是由對(duì)象或?qū)ο箝g關(guān)系來(lái)表示的。 (從某種意義上說(shuō),按照馮·諾依曼的“存儲(chǔ)程序計(jì)算機(jī)”模型,代碼本身也是由對(duì)象來(lái)表示的。)

成都創(chuàng)新互聯(lián)公司專注于商河企業(yè)網(wǎng)站建設(shè),自適應(yīng)網(wǎng)站建設(shè),成都商城網(wǎng)站開(kāi)發(fā)。商河網(wǎng)站建設(shè)公司,為商河等地區(qū)提供建站服務(wù)。全流程按需網(wǎng)站策劃,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)
每個(gè)對(duì)象都有各自的標(biāo)識(shí)號(hào)、類型和值。一個(gè)對(duì)象被創(chuàng)建后,它的 標(biāo)識(shí)號(hào) 就絕不會(huì)改變;你可以將其理解為該對(duì)象在內(nèi)存中的地址。 ‘is‘ 運(yùn)算符可以比較兩個(gè)對(duì)象的標(biāo)識(shí)號(hào)是否相同;id() 函數(shù)能返回一個(gè)代表其標(biāo)識(shí)號(hào)的整數(shù)。
CPython 實(shí)現(xiàn)細(xì)節(jié): 在 CPython 中,id(x) 就是存放 x 的內(nèi)存的地址。
對(duì)象的類型決定該對(duì)象所支持的操作 (例如 “對(duì)象是否有長(zhǎng)度屬性?”) 并且定義了該類型的對(duì)象可能的取值。type() 函數(shù)能返回一個(gè)對(duì)象的類型 (類型本身也是對(duì)象)。與編號(hào)一樣,一個(gè)對(duì)象的 類型 也是不可改變的。1
有些對(duì)象的 值 可以改變。值可以改變的對(duì)象被稱為 可變對(duì)象;值不可以改變的對(duì)象就被稱為 不可變對(duì)象。(一個(gè)不可變?nèi)萜鲗?duì)象如果包含對(duì)可變對(duì)象的引用,當(dāng)后者的值改變時(shí),前者的值也會(huì)改變;但是該容器仍屬于不可變對(duì)象,因?yàn)樗膶?duì)象集是不會(huì)改變的。因此,不可變并不嚴(yán)格等同于值不能改變,實(shí)際含義要更微妙。) 一個(gè)對(duì)象的可變性是由其類型決定的;例如,數(shù)字、字符串和元組是不可變的,而字典和列表是可變的。
對(duì)象絕不會(huì)被顯式地銷毀;然而,當(dāng)無(wú)法訪問(wèn)時(shí)它們可能會(huì)被作為垃圾回收。允許具體的實(shí)現(xiàn)推遲垃圾回收或完全省略此機(jī)制 —- 如何實(shí)現(xiàn)垃圾回收是實(shí)現(xiàn)的質(zhì)量問(wèn)題,只要可訪問(wèn)的對(duì)象不會(huì)被回收即可。
CPython 實(shí)現(xiàn)細(xì)節(jié): CPython 目前使用帶有 (可選) 延遲檢測(cè)循環(huán)鏈接垃圾的引用計(jì)數(shù)方案,會(huì)在對(duì)象不可訪問(wèn)時(shí)立即回收其中的大部分,但不保證回收包含循環(huán)引用的垃圾。請(qǐng)查看 gc 模塊的文檔了解如何控制循環(huán)垃圾的收集相關(guān)信息。其他實(shí)現(xiàn)會(huì)有不同的行為方式,CPython 現(xiàn)有方式也可能改變。不要依賴不可訪問(wèn)對(duì)象的立即終結(jié)機(jī)制 (所以你應(yīng)當(dāng)總是顯式地關(guān)閉文件)。
注意:使用實(shí)現(xiàn)的跟蹤或調(diào)試功能可能令正常情況下會(huì)被回收的對(duì)象繼續(xù)存活。還要注意通過(guò) ‘try…except‘ 語(yǔ)句捕捉異常也可能令對(duì)象保持存活。
有些對(duì)象包含對(duì) “外部” 資源的引用,例如打開(kāi)文件或窗口。當(dāng)對(duì)象被作為垃圾回收時(shí)這些資源也應(yīng)該會(huì)被釋放,但由于垃圾回收并不確保發(fā)生,這些對(duì)象還提供了明確地釋放外部資源的操作,通常為一個(gè) close() 方法。強(qiáng)烈推薦在程序中顯式關(guān)閉此類對(duì)象。’try…finally‘ 語(yǔ)句和 ‘with‘ 語(yǔ)句提供了進(jìn)行此種操作的更便捷方式。
有些對(duì)象包含對(duì)其他對(duì)象的引用;它們被稱為 容器。容器的例子有元組、列表和字典等。這些引用是容器對(duì)象值的組成部分。在多數(shù)情況下,當(dāng)談?wù)撘粋€(gè)容器的值時(shí),我們是指所包含對(duì)象的值而不是其編號(hào);但是,當(dāng)我們談?wù)撘粋€(gè)容器的可變性時(shí),則僅指其直接包含的對(duì)象的編號(hào)。因此,如果一個(gè)不可變?nèi)萜?(例如元組) 包含對(duì)一個(gè)可變對(duì)象的引用,則當(dāng)該可變對(duì)象被改變時(shí)容器的值也會(huì)改變。
類型會(huì)影響對(duì)象行為的幾乎所有方面。甚至對(duì)象編號(hào)的重要性也在某種程度上受到影響: 對(duì)于不可變類型,會(huì)得出新值的運(yùn)算實(shí)際上會(huì)返回對(duì)相同類型和取值的任一現(xiàn)有對(duì)象的引用,而對(duì)于可變類型來(lái)說(shuō)這是不允許的。例如在 a = 1; b = 1 之后,a 和 b 可能會(huì)也可能不會(huì)指向同一個(gè)值為一的對(duì)象,這取決于具體實(shí)現(xiàn),但是在 c = []; d = [] 之后,c 和 d 保證會(huì)指向兩個(gè)不同、單獨(dú)的新建空列表。(請(qǐng)注意 c = d = [] 則是將同一個(gè)對(duì)象賦值給 c 和 d。)
3.2. 標(biāo)準(zhǔn)類型層級(jí)結(jié)構(gòu)
以下是 Python 內(nèi)置類型的列表。擴(kuò)展模塊 (具體實(shí)現(xiàn)會(huì)以 C, Java 或其他語(yǔ)言編寫(xiě)) 可以定義更多的類型。未來(lái)版本的 Python 可能會(huì)加入更多的類型 (例如有理數(shù)、高效存儲(chǔ)的整型數(shù)組等等),不過(guò)新增類型往往都是通過(guò)標(biāo)準(zhǔn)庫(kù)來(lái)提供的。
以下部分類型的描述中包含有 ‘特殊屬性列表’ 段落。這些屬性提供對(duì)具體實(shí)現(xiàn)的訪問(wèn)而非通常使用。它們的定義在未來(lái)可能會(huì)改變。
None
此類型只有一種取值。是一個(gè)具有此值的單獨(dú)對(duì)象。此對(duì)象通過(guò)內(nèi)置名稱 None 訪問(wèn)。在許多情況下它被用來(lái)表示空值,例如未顯式指明返回值的函數(shù)將返回 None。它的邏輯值為假。
NotImplemented
此類型只有一種取值。 是一個(gè)具有該值的單獨(dú)對(duì)象。 此對(duì)象通過(guò)內(nèi)置名稱 NotImplemented 訪問(wèn)。 數(shù)值方法和豐富比較方法如未實(shí)現(xiàn)指定運(yùn)算符表示的運(yùn)算則應(yīng)返回該值。 (解釋器會(huì)根據(jù)具體運(yùn)算符繼續(xù)嘗試反向運(yùn)算或其他回退操作。) 它不應(yīng)被解讀為布爾值。
詳情參見(jiàn) 實(shí)現(xiàn)算術(shù)運(yùn)算。
在 3.9 版更改: 作為布爾值來(lái)解讀 NotImplemented 已被棄用。 雖然它目前會(huì)被解讀為真值,但將同時(shí)發(fā)出 DeprecationWarning。 它將在未來(lái)的 Python 版本中引發(fā) TypeError。
Ellipsis
此類型只有一種取值。是一個(gè)具有此值的單獨(dú)對(duì)象。此對(duì)象通過(guò)字面值 ... 或內(nèi)置名稱 Ellipsis 訪問(wèn)。它的邏輯值為真。
numbers.Number
此類對(duì)象由數(shù)字字面值創(chuàng)建,并會(huì)被作為算術(shù)運(yùn)算符和算術(shù)內(nèi)置函數(shù)的返回結(jié)果。數(shù)字對(duì)象是不可變的;一旦創(chuàng)建其值就不再改變。Python 中的數(shù)字當(dāng)然非常類似數(shù)學(xué)中的數(shù)字,但也受限于計(jì)算機(jī)中的數(shù)字表示方法。
數(shù)字類的字符串表示形式,由 __repr__() 和 __str__() 算出,具有以下特征屬性:
它們是有效的數(shù)字字面值,當(dāng)被傳給它們的類構(gòu)造器時(shí),將會(huì)產(chǎn)生具有原數(shù)字值的對(duì)象。
表示形式會(huì)在可能的情況下采用 10 進(jìn)制。
開(kāi)頭的零,除小數(shù)點(diǎn)前可能存在的單個(gè)零之外,將不會(huì)被顯示。
末尾的零,除小數(shù)點(diǎn)后可能存在的單個(gè)零之外,將不會(huì)被顯示。
正負(fù)號(hào)僅在當(dāng)數(shù)字為負(fù)值時(shí)會(huì)被顯示。
Python 區(qū)分整型數(shù)、浮點(diǎn)型數(shù)和復(fù)數(shù):
numbers.Integral
此類對(duì)象表示數(shù)學(xué)中整數(shù)集合的成員 (包括正數(shù)和負(fù)數(shù))。
整型數(shù)可細(xì)分為兩種類型:
整型 (int)
此類對(duì)象表示任意大小的數(shù)字,僅受限于可用的內(nèi)存 (包括虛擬內(nèi)存)。在變換和掩碼運(yùn)算中會(huì)以二進(jìn)制表示,負(fù)數(shù)會(huì)以 2 的補(bǔ)碼表示,看起來(lái)像是符號(hào)位向左延伸補(bǔ)滿空位。
布爾型 (bool)
此類對(duì)象表示邏輯值 False 和 True。代表
False和True值的兩個(gè)對(duì)象是唯二的布爾對(duì)象。布爾類型是整型的子類型,兩個(gè)布爾值在各種場(chǎng)合的行為分別類似于數(shù)值 0 和 1,例外情況只有在轉(zhuǎn)換為字符串時(shí)分別返回字符串"False"或"True"。
整型數(shù)表示規(guī)則的目的是在涉及負(fù)整型數(shù)的變換和掩碼運(yùn)算時(shí)提供最為合理的解釋。
numbers.Real (float)
此類對(duì)象表示機(jī)器級(jí)的雙精度浮點(diǎn)數(shù)。其所接受的取值范圍和溢出處理將受制于底層的機(jī)器架構(gòu) (以及 C 或 Java 實(shí)現(xiàn))。Python 不支持單精度浮點(diǎn)數(shù);支持后者通常的理由是節(jié)省處理器和內(nèi)存消耗,但這點(diǎn)節(jié)省相對(duì)于在 Python 中使用對(duì)象的開(kāi)銷來(lái)說(shuō)太過(guò)微不足道,因此沒(méi)有理由包含兩種浮點(diǎn)數(shù)而令該語(yǔ)言變得復(fù)雜。
numbers.Complex (complex)
此類對(duì)象以一對(duì)機(jī)器級(jí)的雙精度浮點(diǎn)數(shù)來(lái)表示復(fù)數(shù)值。有關(guān)浮點(diǎn)數(shù)的附帶規(guī)則對(duì)其同樣有效。一個(gè)復(fù)數(shù)值
z的實(shí)部和虛部可通過(guò)只讀屬性z.real和z.imag來(lái)獲取。
序列
此類對(duì)象表示以非負(fù)整數(shù)作為索引的有限有序集。內(nèi)置函數(shù) len() 可返回一個(gè)序列的條目數(shù)量。當(dāng)一個(gè)序列的長(zhǎng)度為 n 時(shí),索引集包含數(shù)字 0, 1, …, n-1。序列 a 的條目 i 可通過(guò) a[i] 選擇。
序列還支持切片: a[i:j] 選擇索引號(hào)為 k 的所有條目,i <= k < j。當(dāng)用作表達(dá)式時(shí),序列的切片就是一個(gè)與序列類型相同的新序列。新序列的索引還是從 0 開(kāi)始。
有些序列還支持帶有第三個(gè) “step” 形參的 “擴(kuò)展切片”: a[i:j:k] 選擇 a 中索引號(hào)為 x 的所有條目,x = i + n*k, n >= 0 且 i <= x < j。
序列可根據(jù)其可變性來(lái)加以區(qū)分:
不可變序列
不可變序列類型的對(duì)象一旦創(chuàng)建就不能再改變。(如果對(duì)象包含對(duì)其他對(duì)象的引用,其中的可變對(duì)象就是可以改變的;但是,一個(gè)不可變對(duì)象所直接引用的對(duì)象集是不能改變的。)
以下類型屬于不可變對(duì)象:
字符串
A string is a sequence of values that represent Unicode code points. All the code points in the range
U+0000 - U+10FFFFcan be represented in a string. Python doesn’t have a char type; instead, every code point in the string is represented as a string object with length1. The built-in function ord() converts a code point from its string form to an integer in the range0 - 10FFFF; chr() converts an integer in the range0 - 10FFFFto the corresponding length1string object. str.encode() can be used to convert a str to bytes using the given text encoding, and bytes.decode() can be used to achieve the opposite.元組
一個(gè)元組中的條目可以是任意 Python 對(duì)象。包含兩個(gè)或以上條目的元組由逗號(hào)分隔的表達(dá)式構(gòu)成。只有一個(gè)條目的元組 (‘單項(xiàng)元組’) 可通過(guò)在表達(dá)式后加一個(gè)逗號(hào)來(lái)構(gòu)成 (一個(gè)表達(dá)式本身不能創(chuàng)建為元組,因?yàn)閳A括號(hào)要用來(lái)設(shè)置表達(dá)式分組)。一個(gè)空元組可通過(guò)一對(duì)內(nèi)容為空的圓括號(hào)創(chuàng)建。
字節(jié)串
字節(jié)串對(duì)象是不可變的數(shù)組。其中每個(gè)條目都是一個(gè) 8 位字節(jié),以取值范圍 0 <= x < 256 的整型數(shù)表示。字節(jié)串字面值 (例如
b'abc') 和內(nèi)置的 bytes() 構(gòu)造器可被用來(lái)創(chuàng)建字節(jié)串對(duì)象。字節(jié)串對(duì)象還可以通過(guò) decode() 方法解碼為字符串。
可變序列
可變序列在被創(chuàng)建后仍可被改變。下標(biāo)和切片標(biāo)注可被用作賦值和 del (刪除) 語(yǔ)句的目標(biāo)。
目前有兩種內(nèi)生可變序列類型:
列表
列表中的條目可以是任意 Python 對(duì)象。列表由用方括號(hào)括起并由逗號(hào)分隔的多個(gè)表達(dá)式構(gòu)成。(注意創(chuàng)建長(zhǎng)度為 0 或 1 的列表無(wú)需使用特殊規(guī)則。)
字節(jié)數(shù)組
字節(jié)數(shù)組對(duì)象屬于可變數(shù)組??梢酝ㄟ^(guò)內(nèi)置的 bytearray() 構(gòu)造器來(lái)創(chuàng)建。除了是可變的 (因而也是不可哈希的),在其他方面字節(jié)數(shù)組提供的接口和功能都與不可變的 bytes 對(duì)象一致。
擴(kuò)展模塊 array 提供了一個(gè)額外的可變序列類型示例,collections 模塊也是如此。
集合類型
此類對(duì)象表示由不重復(fù)且不可變對(duì)象組成的無(wú)序且有限的集合。因此它們不能通過(guò)下標(biāo)來(lái)索引。但是它們可被迭代,也可用內(nèi)置函數(shù) len() 返回集合中的條目數(shù)。集合常見(jiàn)的用處是快速成員檢測(cè),去除序列中的重復(fù)項(xiàng),以及進(jìn)行交、并、差和對(duì)稱差等數(shù)學(xué)運(yùn)算。
對(duì)于集合元素所采用的不可變規(guī)則與字典的鍵相同。注意數(shù)字類型遵循正常的數(shù)字比較規(guī)則: 如果兩個(gè)數(shù)字相等 (例如 1 和 1.0),則同一集合中只能包含其中一個(gè)。
目前有兩種內(nèi)生集合類型:
集合
此類對(duì)象表示可變集合。它們可通過(guò)內(nèi)置的 set() 構(gòu)造器創(chuàng)建,并且創(chuàng)建之后可以通過(guò)方法進(jìn)行修改,例如
add()。凍結(jié)集合
此類對(duì)象表示不可變集合。它們可通過(guò)內(nèi)置的 frozenset() 構(gòu)造器創(chuàng)建。由于 frozenset 對(duì)象不可變且 hashable,它可以被用作另一個(gè)集合的元素或是字典的鍵。
映射
此類對(duì)象表示由任意索引集合所索引的對(duì)象的集合。通過(guò)下標(biāo) a[k] 可在映射 a 中選擇索引為 k 的條目;這可以在表達(dá)式中使用,也可作為賦值或 del 語(yǔ)句的目標(biāo)。內(nèi)置函數(shù) len() 可返回一個(gè)映射中的條目數(shù)。
目前只有一種內(nèi)生映射類型:
字典
此類對(duì)象表示由幾乎任意值作為索引的有限個(gè)對(duì)象的集合。不可作為鍵的值類型只有包含列表或字典或其他可變類型,通過(guò)值而非對(duì)象編號(hào)進(jìn)行比較的值,其原因在于高效的字典實(shí)現(xiàn)需要使用鍵的哈希值以保持一致性。用作鍵的數(shù)字類型遵循正常的數(shù)字比較規(guī)則: 如果兩個(gè)數(shù)字相等 (例如
1和1.0) 則它們均可來(lái)用來(lái)索引同一個(gè)字典條目。字典會(huì)保留插入順序,這意味著鍵將以它們被添加的順序在字典中依次產(chǎn)生。 替換某個(gè)現(xiàn)有的鍵不會(huì)改變其順序,但是移除某個(gè)鍵再重新插入則會(huì)將其添加到末尾而不會(huì)保留其原有位置。
字典是可變的;它們可通過(guò)
{...}標(biāo)注來(lái)創(chuàng)建 (參見(jiàn) 字典顯示 小節(jié))。擴(kuò)展模塊 dbm.ndbm 和 dbm.gnu 提供了額外的映射類型示例,collections 模塊也是如此。
在 3.7 版更改: 在 Python 3.6 版之前字典不會(huì)保留插入順序。 在 CPython 3.6 中插入順序會(huì)被保留,但這在當(dāng)時(shí)被當(dāng)作是一個(gè)實(shí)現(xiàn)細(xì)節(jié)而非確定的語(yǔ)言特性。
可調(diào)用類型
此類型可以被應(yīng)用于函數(shù)調(diào)用操作 (參見(jiàn) 調(diào)用 小節(jié)):
用戶定義函數(shù)
用戶定義函數(shù)對(duì)象可通過(guò)函數(shù)定義來(lái)創(chuàng)建 (參見(jiàn) 函數(shù)定義 小節(jié))。它被調(diào)用時(shí)應(yīng)附帶一個(gè)參數(shù)列表,其中包含的條目應(yīng)與函數(shù)所定義的形參列表一致。
特殊屬性:
屬性
含意
doc該函數(shù)的文檔字符串,沒(méi)有則為
None;不會(huì)被子類繼承。可寫(xiě)
name
該函數(shù)的名稱。
可寫(xiě)
qualname
該函數(shù)的 qualified name。
3.3 新版功能.
可寫(xiě)
module該函數(shù)所屬模塊的名稱,沒(méi)有則為
None。可寫(xiě)
defaults由具有默認(rèn)值的參數(shù)的默認(rèn)參數(shù)值組成的元組,如無(wú)任何參數(shù)具有默認(rèn)值則為
None。可寫(xiě)
code表示編譯后的函數(shù)體的代碼對(duì)象。
可寫(xiě)
globals對(duì)存放該函數(shù)中全局變量的字典的引用 —- 函數(shù)所屬模塊的全局命名空間。
只讀
dict
命名空間支持的函數(shù)屬性。
可寫(xiě)
closureNone或包含該函數(shù)可用變量的綁定的單元的元組。有關(guān)cellcontents屬性的詳情見(jiàn)下。只讀
annotations包含形參標(biāo)注的字典。 字典的鍵是形參名,而如果提供了
‘return’則是用于返回值標(biāo)注。 有關(guān)如何使用此屬性的更多信息,請(qǐng)參閱 對(duì)象注解屬性的最佳實(shí)踐。可寫(xiě)
_kwdefaults僅包含關(guān)鍵字參數(shù)默認(rèn)值的字典。
可寫(xiě)
大部分標(biāo)有 “Writable” 的屬性均會(huì)檢查賦值的類型。
函數(shù)對(duì)象也支持獲取和設(shè)置任意屬性,例如這可以被用來(lái)給函數(shù)附加元數(shù)據(jù)。使用正規(guī)的屬性點(diǎn)號(hào)標(biāo)注獲取和設(shè)置此類屬性。注意當(dāng)前實(shí)現(xiàn)僅支持用戶定義函數(shù)屬性。未來(lái)可能會(huì)增加支持內(nèi)置函數(shù)屬性。
單元對(duì)象具有
cell_contents屬性。這可被用來(lái)獲取以及設(shè)置單元的值。有關(guān)函數(shù)定義的額外信息可以從其代碼對(duì)象中提??;參見(jiàn)下文對(duì)內(nèi)部類型的描述。 cell 類型可以在 types 模塊中訪問(wèn)。
實(shí)例方法
實(shí)例方法用于結(jié)合類、類實(shí)例和任何可調(diào)用對(duì)象 (通常為用戶定義函數(shù))。
特殊的只讀屬性:
__self__為類實(shí)例對(duì)象本身,__func__為函數(shù)對(duì)象;__doc__為方法的文檔 (與__func__.__doc__作用相同);__name__ 為方法名稱 (與__func__.__name__作用相同);__module__為方法所屬模塊的名稱,沒(méi)有則為None。方法還支持獲取 (但不能設(shè)置) 下層函數(shù)對(duì)象的任意函數(shù)屬性。
用戶定義方法對(duì)象可在獲取一個(gè)類的屬性時(shí)被創(chuàng)建 (也可能通過(guò)該類的一個(gè)實(shí)例),如果該屬性為用戶定義函數(shù)對(duì)象或類方法對(duì)象。
當(dāng)通過(guò)從類實(shí)例獲取一個(gè)用戶定義函數(shù)對(duì)象的方式創(chuàng)建一個(gè)實(shí)例方法對(duì)象時(shí),類實(shí)例對(duì)象的
__self__屬性即為該實(shí)例,并會(huì)綁定方法對(duì)象。該新建方法的__func__屬性就是原來(lái)的函數(shù)對(duì)象。當(dāng)通過(guò)從類或?qū)嵗@取一個(gè)類方法對(duì)象的方式創(chuàng)建一個(gè)實(shí)例對(duì)象時(shí),實(shí)例對(duì)象的
__self__屬性為該類本身,其__func__屬性為類方法對(duì)應(yīng)的下層函數(shù)對(duì)象。當(dāng)一個(gè)實(shí)例方法對(duì)象被調(diào)用時(shí),會(huì)調(diào)用對(duì)應(yīng)的下層函數(shù) (
__func__),并將類實(shí)例 (__self__) 插入?yún)?shù)列表的開(kāi)頭。例如,當(dāng)C是一個(gè)包含了f()函數(shù)定義的類,而x是C的一個(gè)實(shí)例,則調(diào)用x.f(1)就等同于調(diào)用C.f(x, 1)。當(dāng)一個(gè)實(shí)例方法對(duì)象是衍生自一個(gè)類方法對(duì)象時(shí),保存在
__self__中的 “類實(shí)例” 實(shí)際上會(huì)是該類本身,因此無(wú)論是調(diào)用x.f(1)還是C.f(1)都等同于調(diào)用f(C,1),其中f為對(duì)應(yīng)的下層函數(shù)。請(qǐng)注意從函數(shù)對(duì)象到實(shí)例方法對(duì)象的變換會(huì)在每一次從實(shí)例獲取屬性時(shí)發(fā)生。在某些情況下,一種高效的優(yōu)化方式是將屬性賦值給一個(gè)本地變量并調(diào)用該本地變量。還要注意這樣的變換只發(fā)生于用戶定義函數(shù);其他可調(diào)用對(duì)象 (以及所有不可調(diào)用對(duì)象) 在被獲取時(shí)都不會(huì)發(fā)生變換。還有一個(gè)需要關(guān)注的要點(diǎn)是作為一個(gè)類實(shí)例屬性的用戶定義函數(shù)不會(huì)被轉(zhuǎn)換為綁定方法;這樣的變換 僅當(dāng) 函數(shù)是類屬性時(shí)才會(huì)發(fā)生。
生成器函數(shù)
一個(gè)使用 yield 語(yǔ)句(見(jiàn) yield 語(yǔ)句 章節(jié))的函數(shù)或方法被稱為 生成器函數(shù)。 這樣的函數(shù)在被調(diào)用時(shí),總是返回一個(gè)可以執(zhí)行該函數(shù)體的 iterator 對(duì)象:調(diào)用該迭代器的 iterator.__next__() 方法將導(dǎo)致這個(gè)函數(shù)一直運(yùn)行到它使用
yield語(yǔ)句提供一個(gè)值。 當(dāng)這個(gè)函數(shù)執(zhí)行 return 語(yǔ)句或到達(dá)函數(shù)體末尾時(shí),將引發(fā) StopIteration 異常并且該迭代器將到達(dá)所返回的值集合的末尾。協(xié)程函數(shù)
使用 async def 來(lái)定義的函數(shù)或方法就被稱為 協(xié)程函數(shù)。這樣的函數(shù)在被調(diào)用時(shí)會(huì)返回一個(gè) coroutine 對(duì)象。它可能包含 await 表達(dá)式以及 async with 和 async for 語(yǔ)句。詳情可參見(jiàn) 協(xié)程對(duì)象 一節(jié)。
異步生成器函數(shù)
使用 async def 來(lái)定義并使用了 yield 語(yǔ)句的函數(shù)或方法被稱為 異步生成器函數(shù)。 這樣的函數(shù)在被調(diào)用時(shí),將返回一個(gè) asynchronous iterator 對(duì)象,該對(duì)象可在 async for 語(yǔ)句中被用來(lái)執(zhí)行函數(shù)體。
調(diào)用異步迭代器的 aiterator.__anext__ 方法將返回一個(gè) awaitable,此對(duì)象會(huì)在被等待時(shí)執(zhí)行直到使用 yield 產(chǎn)生一個(gè)值。 當(dāng)函數(shù)執(zhí)行到空的 return 語(yǔ)句或函數(shù)末尾時(shí),將會(huì)引發(fā) StopAsyncIteration 異常并且異步迭代器也將到達(dá)要產(chǎn)生的值集合的末尾。
內(nèi)置函數(shù)
內(nèi)置函數(shù)對(duì)象是對(duì)于 C 函數(shù)的外部封裝。內(nèi)置函數(shù)的例子包括 len() 和 math.sin() (math 是一個(gè)標(biāo)準(zhǔn)內(nèi)置模塊)。內(nèi)置函數(shù)參數(shù)的數(shù)量和類型由 C 函數(shù)決定。特殊的只讀屬性:
__doc__是函數(shù)的文檔字符串,如果沒(méi)有則為None; __name__ 是函數(shù)的名稱;__self__設(shè)定為None(參見(jiàn)下一條目);__module__是函數(shù)所屬模塊的名稱,如果沒(méi)有則為None。內(nèi)置方法
此類型實(shí)際上是內(nèi)置函數(shù)的另一種形式,只不過(guò)還包含了一個(gè)傳入 C 函數(shù)的對(duì)象作為隱式的額外參數(shù)。內(nèi)置方法的一個(gè)例子是
alist.append(),其中 alist 為一個(gè)列表對(duì)象。在此示例中,特殊的只讀屬性__self__會(huì)被設(shè)為 alist 所標(biāo)記的對(duì)象。類
類是可調(diào)用對(duì)象。 這些對(duì)象通常是用作創(chuàng)建自身實(shí)例的“工廠”,但類也可以有重載 __new__() 的變體類型。 調(diào)用的參數(shù)會(huì)傳遞給
__new__(),并且在通常情況下,也會(huì)傳遞給 __init__() 來(lái)初始化新的實(shí)例。to initialize the new instance.類實(shí)例
任意類的實(shí)例可以通過(guò)在其所屬類中定義 __call__() 方法變成可調(diào)用對(duì)象。
模塊
模塊是 Python 代碼的基本組織單元,由 導(dǎo)入系統(tǒng) 創(chuàng)建,由 import 語(yǔ)句發(fā)起調(diào)用,或者通過(guò) importlib.import_module() 和內(nèi)置的 __import__() 等函數(shù)發(fā)起調(diào)用。 模塊對(duì)象具有由字典對(duì)象實(shí)現(xiàn)的命名空間(這是被模塊中定義的函數(shù)的 __globals__ 屬性引用的字典)。 屬性引用被轉(zhuǎn)換為該字典中的查找,例如 m.x 相當(dāng)于 m.__dict__["x"]。 模塊對(duì)象不包含用于初始化模塊的代碼對(duì)象(因?yàn)槌跏蓟瓿珊蟛恍枰?/p>
屬性賦值會(huì)更新模塊的命名空間字典,例如 m.x = 1 等同于 m.__dict__["x"] = 1。
預(yù)先定義的(可寫(xiě))屬性:
__name__
模塊的名稱。
__doc__模塊的文檔字符串,如果不可用則為
None。__file__
被加載模塊所對(duì)應(yīng)文件的路徑名稱,如果它是從文件加載的話。 對(duì)于某些類型的模塊來(lái)說(shuō) __file__ 屬性可能是缺失的,例如被靜態(tài)鏈接到解釋器中的 C 模塊。 對(duì)于從共享庫(kù)動(dòng)態(tài)加載的擴(kuò)展模塊來(lái)說(shuō),它將是共享庫(kù)文件的路徑名稱。
__annotations__包含在模塊體執(zhí)行期間收集的 變量標(biāo)注 的字典。 有關(guān)使用
__annotations__的最佳實(shí)踐,請(qǐng)參閱 對(duì)象注解屬性的最佳實(shí)踐。
特殊的只讀屬性: __dict__ 為以字典對(duì)象表示的模塊命名空間。
CPython 實(shí)現(xiàn)細(xì)節(jié): 由于 CPython 清理模塊字典的設(shè)定,當(dāng)模塊離開(kāi)作用域時(shí)模塊字典將會(huì)被清理,即使該字典還有活動(dòng)的引用。想避免此問(wèn)題,可復(fù)制該字典或保持模塊狀態(tài)以直接使用其字典。
自定義類
自定義類這種類型一般通過(guò)類定義來(lái)創(chuàng)建 (參見(jiàn) 類定義 一節(jié))。每個(gè)類都有通過(guò)一個(gè)字典對(duì)象實(shí)現(xiàn)的獨(dú)立命名空間。類屬性引用會(huì)被轉(zhuǎn)化為在此字典中查找,例如 C.x 會(huì)被轉(zhuǎn)化為 C.__dict__["x"] (不過(guò)也存在一些鉤子對(duì)象以允許其他定位屬性的方式)。當(dāng)未在其中發(fā)現(xiàn)某個(gè)屬性名稱時(shí),會(huì)繼續(xù)在基類中查找。這種基類查找使用 C3 方法解析順序,即使存在 ‘鉆石形’ 繼承結(jié)構(gòu)即有多條繼承路徑連到一個(gè)共同祖先也能保持正確的行為。有關(guān) Python 使用的 C3 MRO 的詳情可查看配合 2.3 版發(fā)布的文檔 https://www.python.org/download/releases/2.3/mro/.
當(dāng)一個(gè)類屬性引用 (假設(shè)類名為 C) 會(huì)產(chǎn)生一個(gè)類方法對(duì)象時(shí),它將轉(zhuǎn)化為一個(gè) __self__ 屬性為 C 的實(shí)例方法對(duì)象。當(dāng)其會(huì)產(chǎn)生一個(gè)靜態(tài)方法對(duì)象時(shí),它將轉(zhuǎn)化為該靜態(tài)方法對(duì)象所封裝的對(duì)象。從類的 __dict__ 所包含內(nèi)容以外獲取屬性的其他方式請(qǐng)參看 實(shí)現(xiàn)描述器 一節(jié)。
類屬性賦值會(huì)更新類的字典,但不會(huì)更新基類的字典。
類對(duì)象可被調(diào)用 (見(jiàn)上文) 以產(chǎn)生一個(gè)類實(shí)例 (見(jiàn)下文)。
特殊屬性:
__name__
類的名稱。
__module__類定義所在模塊的名稱。
__dict__
包含類命名空間的字典。
__bases__
包含基類的元組,按它們?cè)诨惲斜碇械某霈F(xiàn)先后排序。
__doc__類的文檔字符串,如果未定義則為
None。
__annotations__包含在類體執(zhí)行期間收集的 變量標(biāo)注 的字典。 有關(guān)使用
__annotations__的最佳實(shí)踐,請(qǐng)參閱 對(duì)象注解屬性的最佳實(shí)踐。
類實(shí)例
類實(shí)例可通過(guò)調(diào)用類對(duì)象來(lái)創(chuàng)建(見(jiàn)上文)。 每個(gè)類實(shí)例都有通過(guò)一個(gè)字典對(duì)象實(shí)現(xiàn)的獨(dú)立命名空間,屬性引用會(huì)首先在此字典中查找。 當(dāng)未在其中發(fā)現(xiàn)某個(gè)屬性,而實(shí)例對(duì)應(yīng)的類中有該屬性時(shí),會(huì)繼續(xù)在類屬性中查找。 如果找到的類屬性為一個(gè)用戶自定義函數(shù)對(duì)象,它會(huì)被轉(zhuǎn)化為實(shí)例方法對(duì)象,其 __self__ 屬性即該實(shí)例。 靜態(tài)方法和類方法對(duì)象也會(huì)被轉(zhuǎn)化;參見(jiàn)上文的“類”小節(jié)。 要了解其他通過(guò)類實(shí)例來(lái)獲取相應(yīng)類屬性的方式請(qǐng)參閱 實(shí)現(xiàn)描述器 小節(jié),這樣得到的屬性可能與實(shí)際存放在類的 __dict__ 中的對(duì)象不同。 如果未找到類屬性,而對(duì)象所屬的類具有 __getattr__() 方法,則會(huì)調(diào)用該方法來(lái)滿足查找要求。
屬性賦值和刪除會(huì)更新實(shí)例的字典,但絕不會(huì)更新類的字典。 如果類具有 __setattr__() 或 __delattr__() 方法,則將調(diào)用該方法而不再直接更新實(shí)例的字典。
如果類實(shí)例具有某些特殊名稱的方法,就可以偽裝為數(shù)字、序列或映射。參見(jiàn) 特殊方法名稱 一節(jié)。
特殊屬性: __dict__ 為屬性字典; __class__ 為實(shí)例對(duì)應(yīng)的類。
I/O 對(duì)象 (或稱文件對(duì)象)
file object 表示一個(gè)打開(kāi)的文件。有多種快捷方式可用來(lái)創(chuàng)建文件對(duì)象: open() 內(nèi)置函數(shù),以及 os.popen(), os.fdopen() 和 socket 對(duì)象的 makefile() 方法 (還可能使用某些擴(kuò)展模塊所提供的其他函數(shù)或方法)。
sys.stdin, sys.stdout 和 sys.stderr 會(huì)初始化為對(duì)應(yīng)于解釋器標(biāo)準(zhǔn)輸入、輸出和錯(cuò)誤流的文件對(duì)象;它們都會(huì)以文本模式打開(kāi),因此都遵循 io.TextIOBase 抽象類所定義的接口。
內(nèi)部類型
某些由解釋器內(nèi)部使用的類型也被暴露給用戶。它們的定義可能隨未來(lái)解釋器版本的更新而變化,為內(nèi)容完整起見(jiàn)在此處一并介紹。
代碼對(duì)象
代碼對(duì)象表示 編譯為字節(jié)的 可執(zhí)行 Python 代碼,或稱 bytecode。代碼對(duì)象和函數(shù)對(duì)象的區(qū)別在于函數(shù)對(duì)象包含對(duì)函數(shù)全局對(duì)象 (函數(shù)所屬的模塊) 的顯式引用,而代碼對(duì)象不包含上下文;而且默認(rèn)參數(shù)值會(huì)存放于函數(shù)對(duì)象而不是代碼對(duì)象內(nèi) (因?yàn)樗鼈儽硎驹谶\(yùn)行時(shí)算出的值)。與函數(shù)對(duì)象不同,代碼對(duì)象不可變,也不包含對(duì)可變對(duì)象的引用 (不論是直接還是間接)。
Special read-only attributes:
co_namegives the function name;co_qualnamegives the fully qualified function name;co_argcountis the total number of positional arguments (including positional-only arguments and arguments with default values);co_posonlyargcountis the number of positional-only arguments (including arguments with default values);co_kwonlyargcountis the number of keyword-only arguments (including arguments with default values);co_nlocalsis the number of local variables used by the function (including arguments);co_varnamesis a tuple containing the names of the local variables (starting with the argument names);co_cellvarsis a tuple containing the names of local variables that are referenced by nested functions;co_freevarsis a tuple containing the names of free variables;co_codeis a string representing the sequence of bytecode instructions;co_constsis a tuple containing the literals used by the bytecode;co_namesis a tuple containing the names used by the bytecode;co_filenameis the filename from which the code was compiled;co_firstlinenois the first line number of the function;co_lnotabis a string encoding the mapping from bytecode offsets to line numbers (for details see the source code of the interpreter);co_stacksizeis the required stack size;co_flagsis an integer encoding a number of flags for the interpreter.以下是可用于
co_flags的標(biāo)志位定義:如果函數(shù)使用*arguments語(yǔ)法來(lái)接受任意數(shù)量的位置參數(shù),則0x04位被設(shè)置;如果函數(shù)使用**keywords語(yǔ)法來(lái)接受任意數(shù)量的關(guān)鍵字參數(shù),則0x08位被設(shè)置;如果函數(shù)是一個(gè)生成器,則0x20位被設(shè)置。未來(lái)特性聲明 (
from __future__ import division) 也使用co_flags中的標(biāo)志位來(lái)指明代碼對(duì)象的編譯是否啟用特定的特性: 如果函數(shù)編譯時(shí)啟用未來(lái)除法特性則設(shè)置0x2000位; 在更早的 Python 版本中則使用0x10和0x1000位。co_flags中的其他位被保留為內(nèi)部使用。如果代碼對(duì)象表示一個(gè)函數(shù),
co_consts中的第一項(xiàng)將是函數(shù)的文檔字符串,如果未定義則為None。codeobject.co_positions()
Returns an iterable over the source code positions of each bytecode instruction in the code object.
The iterator returns tuples containing the
(start_line, end_line, start_column, end_column). The i-th tuple corresponds to the position of the source code that compiled to the i-th instruction. Column information is 0-indexed utf-8 byte offsets on the given source line.This positional information can be missing. A non-exhaustive lists of cases where this may happen:
Running the interpreter with -X
no_debug_ranges.Loading a pyc file compiled while using -X
no_debug_ranges.Position tuples corresponding to artificial instructions.
Line and column numbers that can’t be represented due to implementation specific limitations.
When this occurs, some or all of the tuple elements can be None.
3.11 新版功能.
備注
This feature requires storing column positions in code objects which may result in a small increase of disk usage of compiled Python files or interpreter memory usage. To avoid storing the extra information and/or deactivate printing the extra traceback information, the -X
no_debug_rangescommand line flag or the PYTHONNODEBUGRANGES environment variable can be used.
幀對(duì)象
幀對(duì)象表示執(zhí)行幀。它們可能出現(xiàn)在回溯對(duì)象中 (見(jiàn)下文),還會(huì)被傳遞給注冊(cè)跟蹤函數(shù)。
特殊的只讀屬性:
f_back為前一堆棧幀 (指向調(diào)用者),如是最底層堆棧幀則為None;f_code為此幀中所執(zhí)行的代碼對(duì)象;f_locals為用于查找本地變量的字典;f_globals則用于查找全局變量;f_builtins用于查找內(nèi)置 (固有) 名稱;f_lasti給出精確指令 (這是代碼對(duì)象的字節(jié)碼字符串的一個(gè)索引)。訪問(wèn)
f_code會(huì)引發(fā)一個(gè) 審計(jì)事件object.__getattr__,附帶參數(shù)obj和"f_code"。特殊的可寫(xiě)屬性:
f_trace,如果不為None,則是在代碼執(zhí)行期間調(diào)用各類事件的函數(shù) (由調(diào)試器使用)。通常每個(gè)新源碼行會(huì)觸發(fā)一個(gè)事件 - 這可以通過(guò)將f_trace_lines設(shè)為 False 來(lái)禁用。具體的實(shí)現(xiàn) 可能 會(huì)通過(guò)將
f_trace_opcodes設(shè)為 True 來(lái)允許按操作碼請(qǐng)求事件。請(qǐng)注意如果跟蹤函數(shù)引發(fā)的異常逃逸到被跟蹤的函數(shù)中,這可能會(huì)導(dǎo)致未定義的解釋器行為。f_lineno為幀的當(dāng)前行號(hào) —- 在這里寫(xiě)入從一個(gè)跟蹤函數(shù)內(nèi)部跳轉(zhuǎn)的指定行 (僅用于最底層的幀)。調(diào)試器可以通過(guò)寫(xiě)入 f_lineno 實(shí)現(xiàn)一個(gè) Jump 命令 (即設(shè)置下一語(yǔ)句)。幀對(duì)象支持一個(gè)方法:
frame.clear()
此方法清除該幀持有的全部對(duì)本地變量的引用。而且如果該幀屬于一個(gè)生成器,生成器會(huì)被完成。這有助于打破包含幀對(duì)象的循環(huán)引用 (例如當(dāng)捕獲一個(gè)異常并保存其回溯在之后使用)。
如果該幀當(dāng)前正在執(zhí)行則會(huì)引發(fā) RuntimeError。
3.4 新版功能.
回溯對(duì)象
回溯對(duì)象表示一個(gè)異常的棧跟蹤記錄。當(dāng)異常發(fā)生時(shí)會(huì)隱式地創(chuàng)建一個(gè)回溯對(duì)象,也可能通過(guò)調(diào)用 types.TracebackType 顯式地創(chuàng)建。
對(duì)于隱式地創(chuàng)建的回溯對(duì)象,當(dāng)查找異常句柄使得執(zhí)行棧展開(kāi)時(shí),會(huì)在每個(gè)展開(kāi)層級(jí)的當(dāng)前回溯之前插入一個(gè)回溯對(duì)象。當(dāng)進(jìn)入一個(gè)異常句柄時(shí),棧跟蹤將對(duì)程序啟用。(參見(jiàn) try 語(yǔ)句 一節(jié)。) 它可作為
sys.exc_info()所返回的元組的第三項(xiàng),以及所捕獲異常的__traceback__屬性被獲取。當(dāng)程序不包含可用的句柄時(shí),棧跟蹤會(huì) (以良好的格式) 寫(xiě)入標(biāo)準(zhǔn)錯(cuò)誤流;如果解釋器處于交互模式,它也可作為
sys.last_traceback對(duì)用戶啟用。對(duì)于顯式創(chuàng)建的回溯對(duì)象,則由回溯對(duì)象的創(chuàng)建者來(lái)決定應(yīng)該如何鏈接
tb_next屬性來(lái)構(gòu)成完整的棧跟蹤。特殊的只讀屬性:
tb_frame指向當(dāng)前層級(jí)的執(zhí)行幀;tb_lineno給出發(fā)生異常所在的行號(hào);tb_lasti標(biāo)示具體指令。如果異常發(fā)生于沒(méi)有匹配的 except 子句或有 finally 子句的 try 語(yǔ)句中,回溯對(duì)象中的行號(hào)和最后指令可能與相應(yīng)幀對(duì)象中行號(hào)不同。訪問(wèn)
tb_frame會(huì)引發(fā)一個(gè) 審計(jì)事件object.__getattr__,附帶參數(shù)obj和"tb_frame"。特殊的可寫(xiě)屬性:
tb_next為棧跟蹤中的下一層級(jí) (通往發(fā)生異常的幀),如果沒(méi)有下一層級(jí)則為None。在 3.7 版更改: 回溯對(duì)象現(xiàn)在可以使用 Python 代碼顯式地實(shí)例化,現(xiàn)有實(shí)例的
tb_next屬性可以被更新。切片對(duì)象
切片對(duì)象被用來(lái)表示 __getitem__() 方法所使用的切片。 該對(duì)象也可使用內(nèi)置的 slice() 函數(shù)來(lái)創(chuàng)建。
特殊的只讀屬性:
start為下界;stop為上界;step為步長(zhǎng)值; 各值如省略則為None。這些屬性可具有任意類型。切片對(duì)象支持一個(gè)方法:
slice.indices(self, length)
此方法接受一個(gè)整型參數(shù) length 并計(jì)算在切片對(duì)象被應(yīng)用到 length 指定長(zhǎng)度的條目序列時(shí)切片的相關(guān)信息應(yīng)如何描述。 其返回值為三個(gè)整型數(shù)組成的元組;這些數(shù)分別為切片的 start 和 stop 索引號(hào)以及 step 步長(zhǎng)值。索引號(hào)缺失或越界則按照與正規(guī)切片相一致的方式處理。
靜態(tài)方法對(duì)象
靜態(tài)方法對(duì)象提供了一種勝過(guò)上文所述將函數(shù)對(duì)象轉(zhuǎn)換為方法對(duì)象的方式。 靜態(tài)方法對(duì)象是對(duì)任意其他對(duì)象的包裝器,通常用來(lái)包裝用戶自定義的方法對(duì)象。 當(dāng)從類或類實(shí)例獲取一個(gè)靜態(tài)方法對(duì)象時(shí),實(shí)際返回的是經(jīng)過(guò)包裝的對(duì)象,它不會(huì)被進(jìn)一步轉(zhuǎn)換。 靜態(tài)方法對(duì)象也是可調(diào)用對(duì)象。 靜態(tài)方法對(duì)象可通過(guò)內(nèi)置的 staticmethod() 構(gòu)造器來(lái)創(chuàng)建。
類方法對(duì)象
類方法對(duì)象和靜態(tài)方法一樣是對(duì)其他對(duì)象的封裝,會(huì)改變從類或類實(shí)例獲取該對(duì)象的方式。類方法對(duì)象在此類獲取操作中的行為已在上文 “用戶定義方法” 一節(jié)中描述。類方法對(duì)象可通過(guò)內(nèi)置的 classmethod() 構(gòu)造器來(lái)創(chuàng)建。
3.3. 特殊方法名稱
一個(gè)類可以通過(guò)定義具有特殊名稱的方法來(lái)實(shí)現(xiàn)由特殊語(yǔ)法來(lái)發(fā)起調(diào)用的特定操作(例如算術(shù)運(yùn)算或抽取與切片)。 這是 Python 實(shí)現(xiàn) 運(yùn)算符重載 的方式,允許每個(gè)類自行定義基于該語(yǔ)言運(yùn)算符的特定行為。 舉例來(lái)說(shuō),如果一個(gè)類定義了名為 __getitem__() 的方法,并且 x 是該類的一個(gè)實(shí)例,則 x[i] 基本就等價(jià)于 type(x).__getitem__(x, i)。 除非有說(shuō)明例外情況,在沒(méi)有定義適當(dāng)方法的時(shí)候嘗試執(zhí)行某種操作將引發(fā)一個(gè)異常 (通常為 AttributeError 或 TypeError)。
將一個(gè)特殊方法設(shè)為 None 表示對(duì)應(yīng)的操作不可用。 例如,如果一個(gè)類將 __iter__() 設(shè)為 None,則該類就是不可迭代的,因此對(duì)其實(shí)例調(diào)用 iter() 將引發(fā)一個(gè) TypeError (而不會(huì)回退至 __getitem__())。 2
在實(shí)現(xiàn)模擬任何內(nèi)置類型的類時(shí),很重要的一點(diǎn)是模擬的實(shí)現(xiàn)程度對(duì)于被模擬對(duì)象來(lái)說(shuō)應(yīng)當(dāng)是有意義的。例如,提取單個(gè)元素的操作對(duì)于某些序列來(lái)說(shuō)是適宜的,但提取切片可能就沒(méi)有意義。(這種情況的一個(gè)實(shí)例是 W3C 的文檔對(duì)象模型中的 NodeList 接口。)
3.3.1. 基本定制
object.__new__(cls[, …])
調(diào)用以創(chuàng)建一個(gè) cls 類的新實(shí)例。__new__() 是一個(gè)靜態(tài)方法 (因?yàn)槭翘乩阅悴恍枰@式地聲明),它會(huì)將所請(qǐng)求實(shí)例所屬的類作為第一個(gè)參數(shù)。其余的參數(shù)會(huì)被傳遞給對(duì)象構(gòu)造器表達(dá)式 (對(duì)類的調(diào)用)。__new__() 的返回值應(yīng)為新對(duì)象實(shí)例 (通常是 cls 的實(shí)例)。
Typical implementations create a new instance of the class by invoking the superclass’s __new__() method using super().__new__(cls[, ...]) with appropriate arguments and then modifying the newly created instance as necessary before returning it.
如果 __new__() 在構(gòu)造對(duì)象期間被發(fā)起調(diào)用并且它返回了一個(gè) cls 的實(shí)例,則新實(shí)例的 __init__() 方法將以 __init__(self[, ...]) 的形式被發(fā)起調(diào)用,其中 self 為新實(shí)例而其余的參數(shù)與被傳給對(duì)象構(gòu)造器的參數(shù)相同。
如果 __new__() 未返回一個(gè) cls 的實(shí)例,則新實(shí)例的 __init__() 方法就不會(huì)被執(zhí)行。
__new__() 的目的主要是允許不可變類型的子類 (例如 int, str 或 tuple) 定制實(shí)例創(chuàng)建過(guò)程。它也常會(huì)在自定義元類中被重載以便定制類創(chuàng)建過(guò)程。
object.__init__(self[, …])
在實(shí)例 (通過(guò) __new__()) 被創(chuàng)建之后,返回調(diào)用者之前調(diào)用。其參數(shù)與傳遞給類構(gòu)造器表達(dá)式的參數(shù)相同。一個(gè)基類如果有 __init__() 方法,則其所派生的類如果也有 __init__() 方法,就必須顯式地調(diào)用它以確保實(shí)例基類部分的正確初始化;例如: super().__init__([args...]).
因?yàn)閷?duì)象是由 __new__() 和 __init__() 協(xié)作構(gòu)造完成的 (由 __new__() 創(chuàng)建,并由 __init__() 定制),所以 __init__() 返回的值只能是 None,否則會(huì)在運(yùn)行時(shí)引發(fā) TypeError。
object.__del__(self)
在實(shí)例將被銷毀時(shí)調(diào)用。 這還被稱為終結(jié)器或析構(gòu)器(不適當(dāng))。 如果一個(gè)基類具有 __del__() 方法,則其所派生的類如果也有 __del__() 方法,就必須顯式地調(diào)用它以確保實(shí)例基類部分的正確清除。
__del__() 方法可以 (但不推薦!) 通過(guò)創(chuàng)建一個(gè)該實(shí)例的新引用來(lái)推遲其銷毀。這被稱為對(duì)象 重生。__del__() 是否會(huì)在重生的對(duì)象將被銷毀時(shí)再次被調(diào)用是由具體實(shí)現(xiàn)決定的 ;當(dāng)前的 CPython 實(shí)現(xiàn)只會(huì)調(diào)用一次。
當(dāng)解釋器退出時(shí)不會(huì)確保為仍然存在的對(duì)象調(diào)用 __del__() 方法。
備注
del x 并不直接調(diào)用 x.__del__() —- 前者會(huì)將 x 的引用計(jì)數(shù)減一,而后者僅會(huì)在 x 的引用計(jì)數(shù)變?yōu)榱銜r(shí)被調(diào)用。
CPython 實(shí)現(xiàn)細(xì)節(jié): It is possible for a reference cycle to prevent the reference count of an object from going to zero. In this case, the cycle will be later detected and deleted by the cyclic garbage collector. A common cause of reference cycles is when an exception has been caught in a local variable. The frame’s locals then reference the exception, which references its own traceback, which references the locals of all frames caught in the traceback.
參見(jiàn)
gc 模塊的文檔。
警告
由于調(diào)用 __del__() 方法時(shí)周邊狀況已不確定,在其執(zhí)行期間發(fā)生的異常將被忽略,改為打印一個(gè)警告到 sys.stderr。特別地:
__del__() 可在任意代碼被執(zhí)行時(shí)啟用,包括來(lái)自任意線程的代碼。如果 __del__() 需要接受鎖或啟用其他阻塞資源,可能會(huì)發(fā)生死鎖,例如該資源已被為執(zhí)行 __del__() 而中斷的代碼所獲取。
__del__() 可以在解釋器關(guān)閉階段被執(zhí)行。因此,它需要訪問(wèn)的全局變量(包含其他模塊)可能已被刪除或設(shè)為
None。Python 會(huì)保證先刪除模塊中名稱以單個(gè)下劃線打頭的全局變量再刪除其他全局變量;如果已不存在其他對(duì)此類全局變量的引用,這有助于確保導(dǎo)入的模塊在 __del__() 方法被調(diào)用時(shí)仍然可用。
object.__repr__(self)
由 repr() 內(nèi)置函數(shù)調(diào)用以輸出一個(gè)對(duì)象的“官方”字符串表示。如果可能,這應(yīng)類似一個(gè)有效的 Python 表達(dá)式,能被用來(lái)重建具有相同取值的對(duì)象(只要有適當(dāng)?shù)沫h(huán)境)。如果這不可能,則應(yīng)返回形式如 <...some useful description...> 的字符串。返回值必須是一個(gè)字符串對(duì)象。如果一個(gè)類定義了 __repr__() 但未定義 __str__(),則在需要該類的實(shí)例的“非正式”字符串表示時(shí)也會(huì)使用 __repr__()。
此方法通常被用于調(diào)試,因此確保其表示的內(nèi)容包含豐富信息且無(wú)歧義是很重要的。
object.__str__(self)
通過(guò) str(object) 以及內(nèi)置函數(shù) format() 和 print() 調(diào)用以生成一個(gè)對(duì)象的“非正式”或格式良好的字符串表示。返回值必須為一個(gè) 字符串 對(duì)象。
此方法與 object.__repr__() 的不同點(diǎn)在于 __str__() 并不預(yù)期返回一個(gè)有效的 Python 表達(dá)式:可以使用更方便或更準(zhǔn)確的描述信息。
內(nèi)置類型 object 所定義的默認(rèn)實(shí)現(xiàn)會(huì)調(diào)用 object.__repr__()。
object.__bytes__(self)
通過(guò) bytes 調(diào)用以生成一個(gè)對(duì)象的字節(jié)串表示。這應(yīng)該返回一個(gè) bytes 對(duì)象。
object.__format__(self, format_spec)
通過(guò) format() 內(nèi)置函數(shù)、擴(kuò)展、格式化字符串字面值 的求值以及 str.format() 方法調(diào)用以生成一個(gè)對(duì)象的“格式化”字符串表示。 format_spec 參數(shù)為包含所需格式選項(xiàng)描述的字符串。 format_spec 參數(shù)的解讀是由實(shí)現(xiàn) __format__() 的類型決定的,不過(guò)大多數(shù)類或是將格式化委托給某個(gè)內(nèi)置類型,或是使用相似的格式化選項(xiàng)語(yǔ)法。
請(qǐng)參看 格式規(guī)格迷你語(yǔ)言 了解標(biāo)準(zhǔn)格式化語(yǔ)法的描述。
返回值必須為一個(gè)字符串對(duì)象。
在 3.4 版更改: object 本身的 __format__ 方法如果被傳入任何非空字符,將會(huì)引發(fā)一個(gè) TypeError。
在 3.7 版更改: object.__format__(x, '') 現(xiàn)在等同于 str(x) 而不再是 format(str(x), '')。
object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)
以上這些被稱為“富比較”方法。運(yùn)算符號(hào)與方法名稱的對(duì)應(yīng)關(guān)系如下:xx.__lt__(y)、x<=y 調(diào)用 x.__le__(y)、x==y 調(diào)用 x.__eq__(y)、x!=y 調(diào)用 x.__ne__(y)、x>y 調(diào)用 x.__gt__(y)、x>=y 調(diào)用 x.__ge__(y)。
如果指定的參數(shù)對(duì)沒(méi)有相應(yīng)的實(shí)現(xiàn),富比較方法可能會(huì)返回單例對(duì)象 NotImplemented。按照慣例,成功的比較會(huì)返回 False 或 True。不過(guò)實(shí)際上這些方法可以返回任意值,因此如果比較運(yùn)算符是要用于布爾值判斷(例如作為 if 語(yǔ)句的條件),Python 會(huì)對(duì)返回值調(diào)用 bool() 以確定結(jié)果為真還是假。
在默認(rèn)情況下,object 通過(guò)使用 is 來(lái)實(shí)現(xiàn) __eq__(),并在比較結(jié)果為假值時(shí)返回 NotImplemented: True if x is y else NotImplemented。 對(duì)于 __ne__(),默認(rèn)會(huì)委托給 __eq__() 并對(duì)結(jié)果取反,除非結(jié)果為 NotImplemented。 比較運(yùn)算符之間沒(méi)有其他隱含關(guān)系或默認(rèn)實(shí)現(xiàn);例如,(xx<=y。 要根據(jù)單根運(yùn)算自動(dòng)生成排序操作,請(qǐng)參看 functools.total_ordering()。
請(qǐng)查看 __hash__() 的相關(guān)段落,了解創(chuàng)建可支持自定義比較運(yùn)算并可用作字典鍵的 hashable 對(duì)象時(shí)要注意的一些事項(xiàng)。
這些方法并沒(méi)有對(duì)調(diào)參數(shù)版本(在左邊參數(shù)不支持該操作但右邊參數(shù)支持時(shí)使用);而是 __lt__() 和 __gt__() 互為對(duì)方的反射, __le__() 和 __ge__() 互為對(duì)方的反射,而 __eq__() 和 __ne__() 則是它們自己的反射。如果兩個(gè)操作數(shù)的類型不同,且右操作數(shù)類型是左操作數(shù)類型的直接或間接子類,則優(yōu)先選擇右操作數(shù)的反射方法,否則優(yōu)先選擇左操作數(shù)的方法。虛擬子類不會(huì)被考慮。
object.__hash__(self)
通過(guò)內(nèi)置函數(shù) hash() 調(diào)用以對(duì)哈希集的成員進(jìn)行操作,屬于哈希集的類型包括 set、frozenset 以及 dict。__hash__() 應(yīng)該返回一個(gè)整數(shù)。對(duì)象比較結(jié)果相同所需的唯一特征屬性是其具有相同的哈希值;建議的做法是把參與比較的對(duì)象全部組件的哈希值混在一起,即將它們打包為一個(gè)元組并對(duì)該元組做哈希運(yùn)算。例如:
def __hash__(self):return hash((self.name, self.nick, self.color))
備注
hash() 會(huì)從一個(gè)對(duì)象自定義的 __hash__() 方法返回值中截?cái)酁?Py_ssize_t 的大小。通常對(duì) 64 位構(gòu)建為 8 字節(jié),對(duì) 32 位構(gòu)建為 4 字節(jié)。如果一個(gè)對(duì)象的 __hash__() 必須在不同位大小的構(gòu)建上進(jìn)行互操作,請(qǐng)確保檢查全部所支持構(gòu)建的寬度。做到這一點(diǎn)的簡(jiǎn)單方法是使用 python -c "import sys; print(sys.hash_info.width)"。
如果一個(gè)類沒(méi)有定義 __eq__() 方法,那么也不應(yīng)該定義 __hash__() 操作;如果它定義了 __eq__() 但沒(méi)有定義 __hash__(),則其實(shí)例將不可被用作可哈希集的項(xiàng)。如果一個(gè)類定義了可變對(duì)象并實(shí)現(xiàn)了 __eq__() 方法,則不應(yīng)該實(shí)現(xiàn) __hash__(),因?yàn)榭晒<膶?shí)現(xiàn)要求鍵的哈希集是不可變的(如果對(duì)象的哈希值發(fā)生改變,它將處于錯(cuò)誤的哈希桶中)。
用戶定義的類默認(rèn)帶有 __eq__() 和 __hash__() 方法;使用它們與任何對(duì)象(自己除外)比較必定不相等,并且 x.__hash__() 會(huì)返回一個(gè)恰當(dāng)?shù)闹狄源_保 x == y 同時(shí)意味著 x is y 且 hash(x) == hash(y)。
一個(gè)類如果重載了 __eq__() 且沒(méi)有定義 __hash__() 則會(huì)將其 __hash__() 隱式地設(shè)為 None。當(dāng)一個(gè)類的 __hash__() 方法為 None 時(shí),該類的實(shí)例將在一個(gè)程序嘗試獲取其哈希值時(shí)正確地引發(fā) TypeError,并會(huì)在檢測(cè) isinstance(obj, collections.abc.Hashable) 時(shí)被正確地識(shí)別為不可哈希對(duì)象。
如果一個(gè)重載了 __eq__() 的類需要保留來(lái)自父類的 __hash__() 實(shí)現(xiàn),則必須通過(guò)設(shè)置 __hash__ = 來(lái)顯式地告知解釋器。
如果一個(gè)沒(méi)有重載 __eq__() 的類需要去掉哈希支持,則應(yīng)該在類定義中包含 __hash__ = None。一個(gè)自定義了 __hash__() 以顯式地引發(fā) TypeError 的類會(huì)被 isinstance(obj, collections.abc.Hashable) 調(diào)用錯(cuò)誤地識(shí)別為可哈希對(duì)象。
備注
在默認(rèn)情況下,str 和 bytes 對(duì)象的 __hash__() 值會(huì)使用一個(gè)不可預(yù)知的隨機(jī)值“加鹽”。 雖然它們?cè)谝粋€(gè)單獨(dú) Python 進(jìn)程中會(huì)保持不變,但它們的值在重復(fù)運(yùn)行的 Python 間是不可預(yù)測(cè)的。
This is intended to provide protection against a denial-of-service caused by carefully chosen inputs that exploit the worst case performance of a dict insertion, O(n2) complexity. See http://www.ocert.org/advisories/ocert-2011-003.html for details.
改變哈希值會(huì)影響集合的迭代次序。Python 也從不保證這個(gè)次序不會(huì)被改變(通常它在 32 位和 64 位構(gòu)建上是不一致的)。
另見(jiàn) PYTHONHASHSEED.
在 3.3 版更改: 默認(rèn)啟用哈希隨機(jī)化。
object.__bool__(self)
調(diào)用此方法以實(shí)現(xiàn)真值檢測(cè)以及內(nèi)置的 bool() 操作;應(yīng)該返回 False 或 True。如果未定義此方法,則會(huì)查找并調(diào)用 __len__() 并在其返回非零值時(shí)視對(duì)象的邏輯值為真。如果一個(gè)類既未定義 __len__() 也未定義 __bool__() 則視其所有實(shí)例的邏輯值為真。
3.3.2. 自定義屬性訪問(wèn)
可以定義下列方法來(lái)自定義對(duì)類實(shí)例屬性訪問(wèn)(x.name 的使用、賦值或刪除)的具體含義.
object.__getattr__(self, name)
當(dāng)默認(rèn)屬性訪問(wèn)因引發(fā) AttributeError 而失敗時(shí)被調(diào)用 (可能是調(diào)用 __getattribute__() 時(shí)由于 name 不是一個(gè)實(shí)例屬性或 self 的類關(guān)系樹(shù)中的屬性而引發(fā)了 AttributeError;或者是對(duì) name 特性屬性調(diào)用 __get__() 時(shí)引發(fā)了 AttributeError)。此方法應(yīng)當(dāng)返回(找到的)屬性值或是引發(fā)一個(gè) AttributeError 異常。
請(qǐng)注意如果屬性是通過(guò)正常機(jī)制找到的,__getattr__() 就不會(huì)被調(diào)用。(這是在 __getattr__() 和 __setattr__() 之間故意設(shè)置的不對(duì)稱性。)這既是出于效率理由也是因?yàn)椴贿@樣設(shè)置的話 __getattr__() 將無(wú)法訪問(wèn)實(shí)例的其他屬性。要注意至少對(duì)于實(shí)例變量來(lái)說(shuō),你不必在實(shí)例屬性字典中插入任何值(而是通過(guò)插入到其他對(duì)象)就可以模擬對(duì)它的完全控制。請(qǐng)參閱下面的 __getattribute__() 方法了解真正獲取對(duì)屬性訪問(wèn)的完全控制權(quán)的辦法。
object.__getattribute__(self, name)
此方法會(huì)無(wú)條件地被調(diào)用以實(shí)現(xiàn)對(duì)類實(shí)例屬性的訪問(wèn)。如果類還定義了 __getattr__(),則后者不會(huì)被調(diào)用,除非 __getattribute__() 顯式地調(diào)用它或是引發(fā)了 AttributeError。此方法應(yīng)當(dāng)返回(找到的)屬性值或是引發(fā)一個(gè) AttributeError 異常。為了避免此方法中的無(wú)限遞歸,其實(shí)現(xiàn)應(yīng)該總是調(diào)用具有相同名稱的基類方法來(lái)訪問(wèn)它所需要的任何屬性,例如 object.__getattribute__(self, name)。
備注
此方法在作為通過(guò)特定語(yǔ)法或內(nèi)置函數(shù)隱式地調(diào)用的結(jié)果的情況下查找特殊方法時(shí)仍可能會(huì)被跳過(guò)。參見(jiàn) 特殊方法查找。
引發(fā)一個(gè) 審計(jì)事件 object.__getattr__,附帶參數(shù) obj, name。
object.__setattr__(self, name, value)
此方法在一個(gè)屬性被嘗試賦值時(shí)被調(diào)用。這個(gè)調(diào)用會(huì)取代正常機(jī)制(即將值保存到實(shí)例字典)。 name 為屬性名稱, value 為要賦給屬性的值。
如果 __setattr__() 想要賦值給一個(gè)實(shí)例屬性,它應(yīng)該調(diào)用同名的基類方法,例如 object.__setattr__(self, name, value)。
引發(fā)一個(gè) 審計(jì)事件 object.__setattr__,附帶參數(shù) obj, name, value。
object.__delattr__(self, name)
類似于 __setattr__() 但其作用為刪除而非賦值。此方法應(yīng)該僅在 del obj.name 對(duì)于該對(duì)象有意義時(shí)才被實(shí)現(xiàn)。
引發(fā)一個(gè) 審計(jì)事件 object.__delattr__,附帶參數(shù) obj, name。
object.__dir__(self)
此方法會(huì)在對(duì)相應(yīng)對(duì)象調(diào)用 dir() 時(shí)被調(diào)用。返回值必須為一個(gè)序列。 dir() 會(huì)把返回的序列轉(zhuǎn)換為列表并對(duì)其排序。
3.3.2.1. 自定義模塊屬性訪問(wèn)
特殊名稱 __getattr__ 和 __dir__ 還可被用來(lái)自定義對(duì)模塊屬性的訪問(wèn)。模塊層級(jí)的 __getattr__ 函數(shù)應(yīng)當(dāng)接受一個(gè)參數(shù),其名稱為一個(gè)屬性名,并返回計(jì)算結(jié)果值或引發(fā)一個(gè) AttributeError。如果通過(guò)正常查找即 object.__getattribute__() 未在模塊對(duì)象中找到某個(gè)屬性,則 __getattr__ 會(huì)在模塊的 __dict__ 中查找,未找到時(shí)會(huì)引發(fā)一個(gè) AttributeError。如果找到,它會(huì)以屬性名被調(diào)用并返回結(jié)果值。
__dir__ 函數(shù)應(yīng)當(dāng)不接受任何參數(shù),并且返回一個(gè)表示模塊中可訪問(wèn)名稱的字符串序列。 此函數(shù)如果存在,將會(huì)重載一個(gè)模塊中的標(biāo)準(zhǔn) dir() 查找。
想要更細(xì)致地自定義模塊的行為(設(shè)置屬性和特性屬性等待),可以將模塊對(duì)象的 __class__ 屬性設(shè)置為一個(gè) types.ModuleType 的子類。例如:
import sysfrom types import ModuleTypeclass VerboseModule(ModuleType):def __repr__(self):return f'Verbose {self.__name__}'def __setattr__(self, attr, value):print(f'Setting {attr}...')super().__setattr__(attr, value)sys.modules[__name__].__class__ = VerboseModule
備注
定義模塊的 __getattr__ 和設(shè)置模塊的 __class__ 只會(huì)影響使用屬性訪問(wèn)語(yǔ)法進(jìn)行的查找 — 直接訪問(wèn)模塊全局變量(不論是通過(guò)模塊內(nèi)的代碼還是通過(guò)對(duì)模塊全局字典的引用)是不受影響的。
在 3.5 版更改: __class__ 模塊屬性改為可寫(xiě)。
3.7 新版功能: __getattr__ 和 __dir__ 模塊屬性。
參見(jiàn)
PEP 562 - 模塊 __getattr__ 和 __dir__
描述用于模塊的 __getattr__ 和 __dir__ 函數(shù)。
3.3.2.2. 實(shí)現(xiàn)描述器
以下方法僅當(dāng)一個(gè)包含該方法的類(稱為 描述器 類)的實(shí)例出現(xiàn)于一個(gè) 所有者 類中的時(shí)候才會(huì)起作用(該描述器必須在所有者類或其某個(gè)上級(jí)類的字典中)。在以下示例中,“屬性”指的是名稱為所有者類 __dict__ 中的特征屬性的鍵名的屬性。
object.__get__(self, instance, owner=None)
調(diào)用此方法以獲取所有者類的屬性(類屬性訪問(wèn))或該類的實(shí)例的屬性(實(shí)例屬性訪問(wèn))。 可選的 owner 參數(shù)是所有者類而 instance 是被用來(lái)訪問(wèn)屬性的實(shí)例,如果通過(guò) owner 來(lái)訪問(wèn)屬性則返回 None。
此方法應(yīng)當(dāng)返回計(jì)算得到的屬性值或是引發(fā) AttributeError 異常。
PEP 252 指明 __get__() 為帶有一至二個(gè)參數(shù)的可調(diào)用對(duì)象。 Python 自身內(nèi)置的描述器支持此規(guī)格定義;但是,某些第三方工具可能要求必須帶兩個(gè)參數(shù)。 Python 自身的 __getattribute__() 實(shí)現(xiàn)總是會(huì)傳入兩個(gè)參數(shù),無(wú)論它們是否被要求提供。
object.__set__(self, instance, value)
調(diào)用此方法以設(shè)置 instance 指定的所有者類的實(shí)例的屬性為新值 value。
請(qǐng)注意,添加 __set__() 或 __delete__() 會(huì)將描述器變成“數(shù)據(jù)描述器”。 更多細(xì)節(jié)請(qǐng)參閱 調(diào)用描述器。
object.__delete__(self, instance)
調(diào)用此方法以刪除 instance 指定的所有者類的實(shí)例的屬性。
屬性 __objclass__ 會(huì)被 inspect 模塊解讀為指定此對(duì)象定義所在的類(正確設(shè)置此屬性有助于動(dòng)態(tài)類屬性的運(yùn)行時(shí)內(nèi)?。?。對(duì)于可調(diào)用對(duì)象來(lái)說(shuō),它可以指明預(yù)期或要求提供一個(gè)特定類型(或子類)的實(shí)例作為第一個(gè)位置參數(shù)(例如,CPython 會(huì)為實(shí)現(xiàn)于 C 中的未綁定方法設(shè)置此屬性)。
3.3.2.3. 調(diào)用描述器
總的說(shuō)來(lái),描述器就是具有“綁定行為”的對(duì)象屬性,其屬性訪問(wèn)已被描述器協(xié)議中的方法所重載: __get__(), __set__() 和 __delete__()。 如果一個(gè)對(duì)象定義了以上方法中的任意一個(gè),它就被稱為描述器。
屬性訪問(wèn)的默認(rèn)行為是從一個(gè)對(duì)象的字典中獲取、設(shè)置或刪除屬性。例如,a.x 的查找順序會(huì)從 a.__dict__['x'] 開(kāi)始,然后是 type(a).__dict__['x'],接下來(lái)依次查找 type(a) 的上級(jí)基類,不包括元類。
但是,如果找到的值是定義了某個(gè)描述器方法的對(duì)象,則 Python 可能會(huì)重載默認(rèn)行為并轉(zhuǎn)而發(fā)起調(diào)用描述器方法。這具體發(fā)生在優(yōu)先級(jí)鏈的哪個(gè)環(huán)節(jié)則要根據(jù)所定義的描述器方法及其被調(diào)用的方式來(lái)決定。
描述器發(fā)起調(diào)用的開(kāi)始點(diǎn)是一個(gè)綁定 a.x。參數(shù)的組合方式依 a 而定:
直接調(diào)用
最簡(jiǎn)單但最不常見(jiàn)的調(diào)用方式是用戶代碼直接發(fā)起調(diào)用一個(gè)描述器方法: x.__get__(a)。
實(shí)例綁定
如果綁定到一個(gè)對(duì)象實(shí)例,a.x 會(huì)被轉(zhuǎn)換為調(diào)用: type(a).__dict__['x'].__get__(a, type(a))。
類綁定
如果綁定到一個(gè)類,A.x 會(huì)被轉(zhuǎn)換為調(diào)用: A.__dict__['x'].__get__(None, A)。
超綁定
A dotted lookup such as super(A, a).x searches a.__class__.__mro__ for a base class B following A and then returns B.__dict__['x'].__get__(a, A). If not a descriptor, x is returned unchanged.
對(duì)于實(shí)例綁定,發(fā)起描述器調(diào)用的優(yōu)先級(jí)取決于定義了哪些描述器方法。 一個(gè)描述器可以定義 __get__(), __set__() 和 __delete__() 的任意組合。 如果它沒(méi)有定義 __get__(),則訪問(wèn)屬性將返回描述器對(duì)象自身,除非對(duì)象的實(shí)例字典中有相應(yīng)的屬性值。 如果描述器定義了 __set__() 和/或 __delete__(),則它是一個(gè)數(shù)據(jù)描述器;如果以上兩個(gè)都未定義,則它是一個(gè)非數(shù)據(jù)描述器。 通常,數(shù)據(jù)描述器會(huì)同時(shí)定義 __get__() 和 __set__(),而非數(shù)據(jù)描述器則只有 __get__() 方法。 定義了 __get__() 和 __set__() (和/或 __delete__()) 的數(shù)據(jù)描述器總是會(huì)重載實(shí)例字典中的定義。 與之相對(duì)地,非數(shù)據(jù)描述器則可被實(shí)例所重載。
Python 方法(包括用 @staticmethod 和 @classmethod 裝飾的方法)都是作為非數(shù)據(jù)描述器來(lái)實(shí)現(xiàn)的。 因而,實(shí)例可以重定義和重載方法。 這允許單個(gè)實(shí)例獲得與相同類的其他實(shí)例不一樣的行為。
property() 函數(shù)是作為數(shù)據(jù)描述器來(lái)實(shí)現(xiàn)的。因此實(shí)例不能重載特性屬性的行為。
3.3.2.4. __slots__
__slots__ 允許我們顯式地聲明數(shù)據(jù)成員(如特征屬性)并禁
文章標(biāo)題:創(chuàng)新互聯(lián)Python教程:3. 數(shù)據(jù)模型
當(dāng)前鏈接:http://www.5511xx.com/article/cohhhes.html


咨詢
建站咨詢
