婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 詳解Python描述符的工作原理

詳解Python描述符的工作原理

熱門標簽:ai電銷機器人的優勢 南陽打電話機器人 聊城語音外呼系統 商家地圖標注海報 地圖標注自己和別人標注區別 海外網吧地圖標注注冊 孝感營銷電話機器人效果怎么樣 打電話機器人營銷 騰訊地圖標注沒法顯示

一、前言

其實,在開發過程中,雖然我們沒有直接使用到描述符,但是它在底層卻無時不刻地被使用到,例如以下這些:

functionbound methodunbound method

裝飾器propertystaticmethodclassmethod

是不是都很熟悉?

這些都與描述符有著千絲萬縷的關系,這篇文章我們就來看一下描述符背后的工作原理。

二、什么是描述符?

在解釋什么是「描述符」之前,我們先來看一個簡單的例子。

這個例子非常簡單,我們在類 A 中定義了一個類屬性 x,然后打印它的值。

其實,除了直接定類屬性之外,我們還可以這樣定義一個類屬性:

仔細看,這次類屬性 x 不再是一個具體的值,而是一個類 TenTen 中定義了一個 __get__ 方法,返回具體的值。

在 Python 中,允許把一個類屬性,托管給一個類,這個屬性就是一個「描述符」。

換句話說,「描述符」是一個「綁定行為」的屬性。

怎么理解這句話?

回憶一下,我們開發時,一般把「行為」叫做什么?是的,「行為」一般指的是一個方法。

所以我們也可以把「描述符」理解為:對象的屬性不再是一個具體的值,而是交給了一個方法去定義。

可以想一下,如果我們用一個方法去定義一個屬性,這么做的好處是什么?

有了方法,我們就可以在方法內實現自己的邏輯,最簡單的,我們可以根據不同的條件,在方法內給屬性賦予不同的值,就像下面這樣:

三、描述符協議

了解了描述符的定義,現在我們把重點放到托管屬性的類上。

其實,一個類屬性想要托管給一個類,這個類內部實現的方法不能是隨便定義的,它必須遵守「描述符協議」,也就是要實現以下幾個方法:

__get__(self, obj, type=None)
__set__(self, obj, value)
__delete__(self, obj)

只要是實現了以上幾個方法的其中一個,那么這個類屬性就可以稱作描述符。

另外,描述符又可以分為「數據描述符」和「非數據描述符」:

只定義了 __get___,叫做非數據描述符
除了定義 __get__ 之外,還定義了 __set__ 或 __delete__,叫做數據描述符

它們兩者有什么區別,我會在下面詳述。

現在我們來看一個包含 __get__ 和 __set__ 方法的描述符例子:

在這例子中,類屬性 age 是一個描述符,它的值取決于 Age 類。

從輸出結果來看,當我們獲取或修改 age 屬性時,調用了 Age 的 __get__ 和 __set__ 方法:

  • 當調用 p1.age 時,__get__ 被調用,參數 obj 是 Person 實例,type 是 type(Person)
  • 當調用 Person.age 時,__get__ 被調用,參數 obj 是 Nonetype 是 type(Person)
  • 當調用 p1.age = 25時,__set__ 被調用,參數 obj 是 Person 實例,value 是25
  • 當調用 p1.age = -1時,__set__ 沒有通過校驗,拋出 ValueError

其中,調用 __set__ 傳入的參數,我們比較容易理解,但是對于 __get__ 方法,通過類或實例調用,傳入的參數是不同的,這是為什么?

這就需要我們了解一下描述符的工作原理。

四、描述符的工作原理

要解釋描述符的工作原理,首先我們需要先從屬性的訪問說起。

在開發時,不知道你有沒有想過這樣一個問題:通常我們寫這樣的代碼 a.b,其背后到底發生了什么?

這里的 a 和 b 可能存在以下情況:

1.a 可能是一個類,也可能是一個實例,我們這里統稱為對象

2.b 可能是一個屬性,也可能是一個方法,方法其實也可以看做是類的屬性

其實,無論是以上哪種情況,在 Python 中,都有一個統一的調用邏輯:

1.先調用 __getattribute__ 嘗試獲得結果

2.如果沒有結果,調用 __getattr__

用代碼表示就是下面這樣:

我們這里需要重點關注一下 __getattribute__,因為它是所有屬性查找的入口,它內部實現的屬性查找順序是這樣的:

1.要查找的屬性,在類中是否是一個描述符

2.如果是描述符,再檢查它是否是一個數據描述符

3.如果是數據描述符,則調用數據描述符的 __get__

4.如果不是數據描述符,則從 __dict__ 中查找

5.如果 __dict__ 中查找不到,再看它是否是一個非數據描述符

6.如果是非數據描述符,則調用非數據描述符的 __get__

7.如果也不是一個非數據描述符,則從類屬性中查找

8.如果類中也沒有這個屬性,拋出 AttributeError 異常

寫成代碼就是下面這樣:

如果不好理解,你最好寫一個程序測試一下,觀察各種情況下的屬性的查找順序。

到這里我們可以看到,在一個對象中查找一個屬性,都是先從 __getattribute__ 開始的。

在 __getattribute__ 中,它會檢查這個類屬性是否是一個描述符,如果是一個描述符,那么就會調用它的 __get__ 方法。但具體的調用細節和傳入的參數是下面這樣的:

如果 a 是一個實例,調用細節為:

所以我們就能看到上面例子輸出的結果。

五、數據描述符和非數據描述符

了解了描述符的工作原理,我們繼續來看數據描述符和非數據描述符的區別。

從定義上來看,它們的區別是:

  • 只定義了 __get___,叫做非數據描述符
  • 除了定義 __get__ 之外,還定義了 __set__ 或 __delete__,叫做數據描述符

此外,我們從上面描述符調用的順序可以看到,在對象中查找屬性時,數據描述符要優先于非數據描述符調用。

在之前的例子中,我們定義了 __get__ 和 __set__,所以那些類屬性都是數據描述符

我們再來看一個非數據描述符的例子:

這段代碼,我們定義了一個相同名字的屬性和方法 foo,如果現在執行 A().foo,你覺得會輸出什么結果?

答案是 abc

為什么打印的是實例屬性 foo 的值,而不是方法 foo 呢?

這就和非數據描述符有關系了。

我們執行 dir(A.foo),觀察結果:

看到了嗎?A 的 foo 方法其實實現了 __get__,我們在上面的分析已經得知:只定義 __get__ 方法的對象,它其實是一個非數據描述符,也就是說,我們在類中定義的方法,其實本身就是一個非數據描述符。

所以,在一個類中,如果存在相同名字的屬性和方法,按照上面所講的 __getattribute__ 中查找屬性的順序,這個屬性就會優先從實例中獲取,如果實例中不存在,才會從非數據描述符中獲取,所以在這里優先查找的是實例屬性 foo 的值。

到這里我們可以總結一下關于描述符的相關知識點:

  • 描述符必須是一個類屬性
  • __getattribute__ 是查找一個屬性(方法)的入口
  • __getattribute__ 定義了一個屬性(方法)的查找順序:數據描述符、實例屬性、非數據描述符、類屬性
  • 如果我們重寫了 __getattribute__ 方法,會阻止描述符的調用
  • 所有方法其實都是一個非數據描述符,因為它定義了 __get__

六、描述符的使用場景

了解了描述符的工作原理,那描述符一般用在哪些業務場景中呢?

在這里我用描述符實現了一個屬性校驗器,你可以參考這個例子,在類似的場景中去使用它。

首先我們定義一個校驗基類 Validator,在 __set__ 方法中先調用 validate 方法校驗屬性是否符合要求,然后再對屬性進行賦值。

現在,當我們對 Person 實例進行初始化時,就可以校驗這些屬性是否符合預定義的規則了。

七、function與method

我們再來看一下,在開發時經常看到的 functionunbound methodbound method 它們之間到底有什么區別?

來看下面這段代碼:

從結果我們可以看出它們的區別:

  • function 準確來說就是一個函數,并且它實現了 __get__ 方法,因此每一個 function 都是一個非數據描述符,而在類中會把 function 放到 __dict__ 中存儲
  • 當 function 被實例調用時,它是一個 bound method
  • 當 function 被類調用時, 它是一個 unbound method

function 是一個非數據描述符,我們之前已經講到了。

而 bound method 和 unbound method 的區別就在于調用方的類型是什么,如果是一個實例,那么這個 function 就是一個 bound method,否則它是一個 unbound method

八、property/staticmethod/classmethod

我們再來看 propertystaticmethodclassmethod

這些裝飾器的實現,默認是 C 來實現的。

其實,我們也可以直接利用 Python 描述符的特性來實現這些裝飾器,

property 的 Python 版實現:

除此之外,你還可以實現其他功能強大的裝飾器。

由此可見,通過描述符我們可以實現強大而靈活的屬性管理功能,對于一些要求屬性控制比較復雜的場景,我們可以選擇用描述符來實現。

到此這篇關于詳解Python描述符的工作原理的文章就介紹到這了,更多相關Python描述符內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • Python基礎詳解之描述符
  • Python描述符descriptor使用原理解析
  • python實現裝飾器、描述符
  • 詳解Python中的Descriptor描述符類
  • Python黑魔法Descriptor描述符的實例解析
  • Python 的描述符 descriptor詳解
  • 解密Python中的描述符(descriptor)

標簽:楊凌 聊城 揚州 六盤水 迪慶 南寧 牡丹江 撫州

巨人網絡通訊聲明:本文標題《詳解Python描述符的工作原理》,本文關鍵詞  詳解,Python,描述,符,的,工作,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《詳解Python描述符的工作原理》相關的同類信息!
  • 本頁收集關于詳解Python描述符的工作原理的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    国产精品亲子乱子伦xxxx裸| 26uuu精品一区二区| 五月天激情综合| 一区二区三区丝袜| 性感美女久久精品| www.久久精品| 制服.丝袜.亚洲.另类.中文| 中文字幕 久热精品 视频在线 | 日韩国产成人精品| 一区二区三区在线免费视频| 国产酒店精品激情| 99久久伊人网影院| 制服丝袜中文字幕亚洲| 日本一区二区动态图| 夜夜嗨av一区二区三区四季av| 亚洲欧美成aⅴ人在线观看| 亚洲一区二区三区不卡国产欧美| 日本伊人精品一区二区三区观看方式| 免费在线视频一区| 欧美日韩日日夜夜| 亚洲精品美国一| 欧美性猛片xxxx免费看久爱| 中文字幕不卡的av| 国产精品一区在线观看你懂的| 91成人免费在线视频| 国产精品久久久久毛片软件| 日本精品视频一区二区三区| 国产三区在线成人av| 高清av一区二区| 亚洲二区在线观看| 色婷婷狠狠综合| 国产麻豆精品theporn| 国产成人亚洲综合色影视| 奇米色一区二区| 日韩一二三区视频| 成人性生交大片免费看中文| 国模冰冰炮一区二区| 国产日韩欧美a| a在线欧美一区| 国产精品欧美综合在线| 99精品视频中文字幕| 中文字幕中文字幕一区| 成人久久久精品乱码一区二区三区| 国产精品成人免费| 欧美日本在线观看| 成人做爰69片免费看网站| 国产丝袜美腿一区二区三区| 成人永久免费视频| 一个色综合网站| 日韩一区中文字幕| 欧美激情一区二区三区蜜桃视频| 欧美一级午夜免费电影| 久久精品一区二区三区四区| www.亚洲国产| 福利一区在线观看| 久久成人久久爱| 成人激情小说网站| 9l国产精品久久久久麻豆| 成人一区在线看| 91在线播放网址| 欧美日本一道本在线视频| 717成人午夜免费福利电影| 欧美一区二区三区在线| 精品国产免费久久| 国产欧美视频在线观看| 亚洲女女做受ⅹxx高潮| 天堂久久久久va久久久久| 日韩精品免费专区| 国产精品乡下勾搭老头1| 97成人超碰视| 日韩欧美国产综合一区| 国产精品色婷婷| 免费日韩伦理电影| 日本韩国精品一区二区在线观看| 欧美美女喷水视频| 国产亚洲成aⅴ人片在线观看| 最新不卡av在线| 国产麻豆精品在线| 日本高清无吗v一区| 久久久精品日韩欧美| 亚洲第一综合色| 91福利国产精品| 日本一区二区三区四区| 日产欧产美韩系列久久99| 91免费观看在线| 久久欧美一区二区| 精品伊人久久久久7777人| 成年人网站91| 奇米精品一区二区三区在线观看 | 亚洲国产中文字幕| 国产欧美精品一区二区三区四区 | 精品成人在线观看| 欧美一区二区三区四区在线观看| 成人午夜视频在线| 亚洲免费观看在线视频| 欧美一卡2卡3卡4卡| 亚洲一区视频在线观看视频| 91精品国产欧美一区二区| 看片的网站亚洲| 26uuu精品一区二区在线观看| 国产伦精一区二区三区| 亚洲一区二区高清| 91精品国产综合久久精品app| 日本亚洲视频在线| 中文字幕一区免费在线观看| 欧美午夜精品电影| 波多野结衣视频一区| 激情综合色综合久久| 亚洲一区二区在线视频| 亚洲精选免费视频| 日韩毛片一二三区| 国产精品理论在线观看| 日韩欧美久久久| 日韩精品一区二区三区四区| 99久久精品费精品国产一区二区| 国产伦精品一区二区三区视频青涩 | 五月婷婷色综合| 高清av一区二区| 中文字幕一区免费在线观看| 国产人伦精品一区二区| 日韩成人精品在线| 日韩精品一二三| 成人免费精品视频| 欧美在线不卡视频| 亚洲午夜久久久| 欧美日韩国产bt| 国产在线日韩欧美| 国产精品毛片高清在线完整版| 精品一区二区av| 欧美一区二区美女| 色欧美片视频在线观看| 成人久久久精品乱码一区二区三区| 国产亚洲va综合人人澡精品 | 欧美日韩精品电影| 欧美美女一区二区在线观看| 亚洲欧美国产高清| 七七婷婷婷婷精品国产| 久久久亚洲精品石原莉奈| 99精品一区二区| 午夜视频一区二区| 久久人人97超碰com| 岛国精品一区二区| 免费观看一级特黄欧美大片| 欧美精品一区二区三区蜜臀| 欧美国产欧美亚州国产日韩mv天天看完整| 国产女人aaa级久久久级 | 韩国欧美一区二区| 色婷婷国产精品综合在线观看| 欧美一区二区三区在线观看| 中文字幕一区二区三区不卡| 韩国在线一区二区| 精品三级在线观看| 久久疯狂做爰流白浆xx| 欧美群妇大交群中文字幕| 亚洲三级在线看| 在线日韩av片| 一区二区高清免费观看影视大全| 成人一级黄色片| 日韩理论片网站| 91麻豆精东视频| 伊人色综合久久天天人手人婷| 97国产一区二区| 亚洲超丰满肉感bbw| 欧美裸体一区二区三区| 日韩成人免费看| 久久蜜臀中文字幕| 成人精品视频一区二区三区尤物| 久久亚洲一级片| 成人理论电影网| 婷婷开心激情综合| 久久亚洲一区二区三区四区| 国产精品亚洲综合一区在线观看| 国产拍揄自揄精品视频麻豆| 成人永久免费视频| 亚洲一区二区综合| 日韩美一区二区三区| 99免费精品在线| 精久久久久久久久久久| 综合网在线视频| 欧美成人一区二区三区片免费 | 久久久午夜电影| 欧美又粗又大又爽| 国产精品一区二区91| 久久精品视频一区二区| 欧美福利视频一区| 粉嫩嫩av羞羞动漫久久久| 亚洲h动漫在线| 亚洲欧美日韩国产成人精品影院| 精品国产污网站| 精品国产乱码久久久久久影片| 91丨国产丨九色丨pron| 精品亚洲成av人在线观看| 三级久久三级久久久| 亚洲综合一区二区精品导航| 亚洲精品水蜜桃| 午夜欧美视频在线观看| 亚洲国产精品一区二区久久恐怖片 | 欧美一级黄色片| 欧美中文字幕亚洲一区二区va在线| 成人一级片网址|