半天鐘的博客元編程相關博文的目錄及鏈接這篇博文是元編程系列博文中的其中一篇、這個系列中其他博文的目錄和連接見下:使用python特性管理實例屬性淺析python屬性描述符(上)淺析python屬性描述符(下)python導入時與運行時python元編程之動態屬性python元編程之類元編程Review在上一篇博文中、我們使用python特性(property)管理了實例屬性,最大的好處是:在使用property裝飾器后," />

日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

淺析 python 屬性描述符(上)

系統 1901 0

轉載自我自己的 github 博客 ——> 半天鐘的博客

元編程相關博文的目錄及鏈接

這篇博文是元編程系列博文中的其中一篇、這個系列中其他博文的目錄和連接見下:

  1. 使用 python 特性管理實例屬性
  2. 淺析 python 屬性描述符(上)
  3. 淺析 python 屬性描述符(下)
  4. python 導入時與運行時
  5. python 元編程之動態屬性
  6. python 元編程之類元編程

Review

在上一篇博文中、我們使用 python 特性(property)管理了實例屬性,最大的好處是:在使用 property 裝飾器后,我們 能夠在通過使用 " . " 這種方便的方式(obj.attr)來訪問實例屬性的同時,為其設置存儲規則。

并且,因為處理存儲的函數都有 @property 或者 @特性名.setter 這種 明顯的裝飾器標志 ,我們 可以很容易的找到處理業務邏輯的核心函數。

然而、 當大量的屬性都需要相同的存取邏輯做控制時 ,例如:水果類的 weight 和 price 的值均不能小于零。 單純的使用 property 依然無法避免代碼的重復。

當重復為 weight 和 price 編寫幾乎相同的代碼時, 重構代碼的時機到了!!!

運用和 property 同宗 的屬性描述符可以很好的避免代碼段的重復。

博文的編寫思路

首先、我會直接亮出使用屬性描述符重構的代碼(基于上一篇博文的 Fruits 類), 用以給你屬性描述符,以及其如何減少重復代碼的直觀印象。

然后、我會仔細的說明 實現屬性描述符需要注意的細節 屬性描述符的性質 及其如何與托管類實例交互。

接著、我會說明為什么 python 特性也是一種屬性描述符

最后、我會舉例說明屬性描述符比之 python 特性和優勢在哪里

使用屬性描述符進行高效管理

下面這段代碼是基于上一篇博文的 Fruit 類進行的重構:

            
              
                class
              
              
                Quantity
              
              
                :
              
              
                def
              
              
                __init__
              
              
                (
              
              self
              
                ,
              
               attrname
              
                )
              
              
                :
              
              
        self
              
                .
              
              attrname 
              
                =
              
               attrname

    
              
                def
              
              
                __get__
              
              
                (
              
              self
              
                ,
              
               instance
              
                ,
              
               owner
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                "get:"
              
              
                +
              
              
                str
              
              
                (
              
              instance
              
                .
              
              description
              
                )
              
              
                +
              
              
                "的"
              
              
                +
              
              
                str
              
              
                (
              
              self
              
                .
              
              attrname
              
                )
              
              
                )
              
              
                return
              
               instance
              
                .
              
              __dict__
              
                [
              
              self
              
                .
              
              attrname
              
                ]
              
              
                def
              
              
                __set__
              
              
                (
              
              self
              
                ,
              
               instance
              
                ,
              
               value
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                "set:"
              
              
                +
              
              
                str
              
              
                (
              
              instance
              
                .
              
              description
              
                )
              
              
                +
              
              
                "的"
              
              
                +
              
              
                str
              
              
                (
              
              self
              
                .
              
              attrname
              
                )
              
              
                )
              
              
                if
              
               value 
              
                >
              
              
                0
              
              
                :
              
              
            instance
              
                .
              
              __dict__
              
                [
              
              self
              
                .
              
              attrname
              
                ]
              
              
                =
              
               value
        
              
                else
              
              
                :
              
              
                raise
              
               ValueError
              
                (
              
              
                "想干嘛呢?"
              
              
                )
              
              
                class
              
              
                Fruits
              
              
                :
              
              

    weight 
              
                =
              
               Quantity
              
                (
              
              
                "weight"
              
              
                )
              
              
    price 
              
                =
              
               Quantity
              
                (
              
              
                "price"
              
              
                )
              
              
                def
              
              
                __init__
              
              
                (
              
              self
              
                ,
              
               price
              
                ,
              
               weight
              
                ,
              
               description
              
                )
              
              
                :
              
              
                # 水果的描述
              
              
        self
              
                .
              
              description 
              
                =
              
               description
        
              
                # 水果的價格
              
              
        self
              
                .
              
              price 
              
                =
              
               price
        
              
                # 水果的重量
              
              
        self
              
                .
              
              weight 
              
                =
              
               weight

    
              
                def
              
              
                subtotal
              
              
                (
              
              self
              
                )
              
              
                :
              
              
                # 小記
              
              
                return
              
               self
              
                .
              
              price 
              
                *
              
               self
              
                .
              
              weight
        

              
                >>
              
              
                >
              
               apple 
              
                =
              
               Fruits
              
                (
              
              
                10
              
              
                ,
              
              
                2
              
              
                ,
              
              
                "apple"
              
              
                )
              
              
                # 1
              
              
                set
              
              
                :
              
              apple的price

              
                set
              
              
                :
              
              apple的weight

              
                >>
              
              
                >
              
               pear 
              
                =
              
               Fruits
              
                (
              
              
                11
              
              
                ,
              
              
                3
              
              
                ,
              
              
                "pear"
              
              
                )
              
              
                set
              
              
                :
              
              pear的price

              
                set
              
              
                :
              
              pear的weight

              
                >>
              
              
                >
              
              
                vars
              
              
                (
              
              apple
              
                )
              
              
                # 2
              
              
                {
              
              
                'description'
              
              
                :
              
              
                'apple'
              
              
                ,
              
              
                'price'
              
              
                :
              
              
                10
              
              
                ,
              
              
                'weight'
              
              
                :
              
              
                2
              
              
                }
              
              
                >>
              
              
                >
              
              
                vars
              
              
                (
              
              pear
              
                )
              
              
                {
              
              
                'description'
              
              
                :
              
              
                'pear'
              
              
                ,
              
              
                'price'
              
              
                :
              
              
                11
              
              
                ,
              
              
                'weight'
              
              
                :
              
              
                3
              
              
                }
              
              
                >>
              
              
                >
              
               apple
              
                .
              
              weight 
              
                # 3
              
              
get
              
                :
              
              apple的weight

              
                2
              
              
                >>
              
              
                >
              
               apple
              
                .
              
              price 
get
              
                :
              
              apple的price

              
                10
              
              
                >>
              
              
                >
              
               apple
              
                .
              
              weight 
              
                =
              
              
                10
              
              
                # 4
              
              
                set
              
              
                :
              
              apple的weight

              
                >>
              
              
                >
              
               apple
              
                .
              
              weight 
              
                # 5
              
              
get
              
                :
              
              apple的weight

              
                10
              
              
                >>
              
              
                >
              
              
                vars
              
              
                (
              
              pear
              
                )
              
              
                # 6
              
              
                {
              
              
                'description'
              
              
                :
              
              
                'pear'
              
              
                ,
              
              
                'price'
              
              
                :
              
              
                11
              
              
                ,
              
              
                'weight'
              
              
                :
              
              
                3
              
              
                }
              
              
                >>
              
              
                >
              
               apple
              
                .
              
              price 
              
                =
              
              
                -
              
              
                1
              
              
                # 7
              
              
Traceback 
              
                (
              
              most recent call last
              
                )
              
              
                :
              
              
                .
              
              
                .
              
              
                .
              
              
ValueError
              
                :
              
               想干嘛呢?

            
          

上例使用屬性描述符類 Quantity 類對 Fruits 類進行了重構,使用了 Quantity 實例作為 Fruits 類的 weight 和 price 的類屬性值。

可以看到、 重構后的 Fruits 類實例有如下行為

  1. 初始化 Fruits 類實例時, 會調用描述符實例的 __set__ magic 方法。
  2. 查看實例 apple 的全部屬性、發現其 有 price 和 weight 實例屬性 。這是由于 __set__ magic 方法使用 instance.__dict__[self.attrname] = value 語句為實例屬性設了值
  3. 可以通過 apple.weight 訪問實例屬性 ,但是其是通過描述符實例的 __get__ magic 方法來訪問的。
  4. 可以通過 apple.weight = 10 這種方式為實例屬性設置值 ,但是其實通過描述符實例的 __set__ magic 方法來訪問的。
  5. 能夠訪問到剛剛為 apple 實例設置的值。
  6. 查看 pear 實例的全部屬性、發現 剛才對 apple 實例的所有操作對 pear 實例毫無影響。
  7. 若設置 value 為負值,那么會拋出異常。

如果你不明白這些行為的原理,沒關系,我會在下一小節解釋屬性描述符的原理,現在你只需要知道,重構后的代碼有著這樣的行為。

重構后的好處

好了,在使用了 Quantity 屬性描述重構了 Fruits 類之后、 我們依然可以使用 " . " 方便的訪問實例屬性,并同時做存儲邏輯的驗證。

而且、**我僅用了 30 行代碼就實現了 weight 和 price 兩個實例屬性的管理。**要知道、上一篇博文中,僅實現了 weight 屬性的管理就寫了 27 行代碼。

不僅是代碼量減少了,如果水果店老板想為所有水果都增加一個折扣屬性(discount)、其也不能為負值。那么我們只需要在 Fruit 類中增加一行代碼 discount = Quantity("discount") 這大大減少了重復代碼,提高了代碼的可重用性。

屬性描述符原理

為了說明白屬性描述符的原理,我將先說明一些專有名詞。

專有名詞

描述符類

  • 實現了描述符協議的類 、比如上例中的 Quantity 類、它實現了描述符類的一些協議( __get__ __set__ )。

實現了 __get__ __set__ __delete__ 方法的類是描述符,只要實現了其中一個就是。

托管類

  • 將描述符實例作為類屬性的類 ,比如上例中的 Fruits 類,他有 weight、price 兩個類屬性,且都被賦予了描述符類的實例。

描述符實例

  • 描述符類的實例 、比如上例中 Fruits 類中就用 Quantity("weight") 創建了一個描述符實例, 通常來講,描述符類的實例會被賦給托管類的類屬性。

托管實例

  • 托管類的實例 、比如上例中的 apple 、 pear。

托管屬性

  • 托管類中由描述符實例處理的公開屬性 、比如上例中 Fruits 類的 類屬性 weight、price

存儲屬性

  • 可以粗略的理解為、托管實例的屬性 、在上例中使用 vars(apple) 得到的結果中 price 和 weight 實例屬性 就是存儲屬性,它們實際 存儲著 * 實例的 * 屬性值

你可能不理解存儲屬性和托管屬性的區別、因為在上例中 托管屬性與存儲屬性同名
那么,你只需要記住: 托管屬性是類(Fruits)屬性、存儲屬性是實例(apple)的屬性。

描述符類與托管類的關系

首先,描述符類與托管類都是類,可以將他們想象成類的工廠、下面兩張圖很好的展示了他們之間的關系:

以下兩張圖修改自《流暢的 python》 第 20 章

淺析 python 屬性描述符(上)_第1張圖片

如上圖、Quantity 作為描述符實例的工廠、 產出了兩個實例并綁定至 Fruits 類的類屬性 weight、price

Fruit 作為托管類實例的工廠、可以產出多個實例、 每一個實例都有兩個存儲屬性 weight、price

淺析 python 屬性描述符(上)_第2張圖片

上圖將描述符的兩個實例抽象成了兩個小機器人、手上拿著一個放大鏡和一個手抓, 放大鏡用于獲取托管類實例的值( __get__ )、手抓用于設置托管類實例的值( __set__ )

值得注意的是、Fruits 工廠不管生產多少實例, 都只能擁有兩個描述符小機器人 ,因為它們是類屬性。

描述符實例如何工作

如果你看過上一篇博文、你可能還記得上一篇博文中的特性的工作流程圖。實際上特性就是一種屬性描述符、所以在這里 Quantity 屬性描述符的工作流程與特性幾乎一致 ,例如: apple.weight = 10 語句的執行過程如下面的流程圖:

淺析 python 屬性描述符(上)_第3張圖片

以上流程、對于 Quantity 這個類型的描述符而言, apple.weight 這樣的代碼的執行流程與上圖幾乎沒有差別,無非是在搜索到有 weight 描述符實例時,調用 __get__ magic 方法;在搜索到有 weight 實例屬性時獲取該屬性的值;都搜索不到則拋出異常。

property 是一種屬性描述符

為什么說 python 特性也是一種屬性描述符呢?讓我們看 python 2.2 之前是如何使用 property的:

property 類實現了完整的描述符協議

            
              
                def
              
              
                get_weight
              
              
                (
              
              instance
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                "get weight"
              
              
                )
              
              
                return
              
               instance
              
                .
              
              __dict__
              
                [
              
              
                "weight"
              
              
                ]
              
              
                def
              
              
                set_weight
              
              
                (
              
              instance
              
                ,
              
               value
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                "set weight"
              
              
                )
              
              
                if
              
               value 
              
                >
              
              
                0
              
              
                :
              
              
        instance
              
                .
              
              __dict__
              
                [
              
              
                "weight"
              
              
                ]
              
              
                =
              
               value
    
              
                else
              
              
                :
              
              
                raise
              
               ValueError
              
                (
              
              
                "想干嘛呢?"
              
              
                )
              
              
                class
              
              
                Fruits
              
              
                :
              
              

    weight 
              
                =
              
              
                property
              
              
                (
              
              get_weight
              
                ,
              
               set_weight
              
                )
              
              
                def
              
              
                __init__
              
              
                (
              
              self
              
                ,
              
               price
              
                ,
              
               weight
              
                ,
              
               description
              
                )
              
              
                :
              
              
                # 水果的描述
              
              
        self
              
                .
              
              description 
              
                =
              
               description
        
              
                # 水果的價格
              
              
        self
              
                .
              
              price 
              
                =
              
               price
        
              
                # 水果的重量
              
              
        self
              
                .
              
              weight 
              
                =
              
               weight

    
              
                def
              
              
                subtotal
              
              
                (
              
              self
              
                )
              
              
                :
              
              
                # 小記
              
              
                return
              
               self
              
                .
              
              price 
              
                *
              
               self
              
                .
              
              weight


              
                >>
              
              
                >
              
               apple 
              
                =
              
               Fruits
              
                (
              
              
                10
              
              
                ,
              
              
                2
              
              
                ,
              
              
                "apple"
              
              
                )
              
              
                set
              
               weight

              
                >>
              
              
                >
              
              
                vars
              
              
                (
              
              apple
              
                )
              
              
                {
              
              
                'description'
              
              
                :
              
              
                'apple'
              
              
                ,
              
              
                'price'
              
              
                :
              
              
                10
              
              
                ,
              
              
                'weight'
              
              
                :
              
              
                2
              
              
                }
              
              
                >>
              
              
                >
              
               apple
              
                .
              
              weight
get weight

              
                2
              
              
                >>
              
              
                >
              
               apple
              
                .
              
              weight 
              
                =
              
              
                10
              
              
                set
              
               weight

              
                >>
              
              
                >
              
               apple
              
                .
              
              weight
get weight

              
                10
              
              
                >>
              
              
                >
              
               apple
              
                .
              
              weight 
              
                =
              
              
                -
              
              
                1
              
              
Traceback 
              
                (
              
              most recent call last
              
                )
              
              
                :
              
              
                .
              
              
                .
              
              
                .
              
              
ValueError
              
                :
              
               想干嘛呢?

            
          

你看出來了嗎?上例中的我們寫了一對 set/get 方法,并用他們生成了一個 property 對象,賦予了 Fruits 類的 weight 類屬性。這和屬性描述符類 Quantity 有太多的相似之處。

實際上 property 類的構造方法返回一個描述符實例,該實例的 __get__ magic方法即是get_weight、 __set__ magic 方法既是 set_weight。

甚至這樣做以后、 也能很好的管理 Fruits 實例的 weight 屬性 ,行為與使用 Quantity 一致。

肯定有人會說、既然這樣, 那我完全沒有必要使用 Quantity 了,直接寫一個特性工廠函數即可!!!
比如:

代碼來自《流暢的 python》第19章

            
              
                def
              
              
                quantity
              
              
                (
              
              storage_name
              
                )
              
              
                :
              
              
                def
              
              
                qty_getter
              
              
                (
              
              instance
              
                )
              
              
                :
              
              
                return
              
               instance
              
                .
              
              __dict__
              
                [
              
              storage_name
              
                ]
              
              
                def
              
              
                qty_setter
              
              
                (
              
              instance
              
                ,
              
               value
              
                )
              
              
                :
              
              
                if
              
               value 
              
                >
              
              
                0
              
              
                :
              
              
            instance
              
                .
              
              __dict__
              
                [
              
              storage_name
              
                ]
              
              
                =
              
               value  
        
              
                else
              
              
                :
              
              
                raise
              
               ValueError
              
                (
              
              
                'value must be > 0'
              
              
                )
              
              
                return
              
              
                property
              
              
                (
              
              qty_getter
              
                ,
              
               qty_setter
              
                )
              
            
          

這樣一來、 weight = Quantity("weight") 就可以轉變為 weight = quantity('weight') 。甚至比創建 Quantity 類的代碼還要短。

但是,對于描述符類來說、依舊有著得天獨厚的優勢, 即面向對象的方式

描述符類能夠繼承

現在,項目的產品經理小姐姐提出了一個合理的需求 —— **Fruits 的描述不能為空!!**這很合理,因為描述為空時,顧客在系統中根本看不到自己買的是哪種水果。

輪到程序猿頭疼了,難道再增加一個描述符類,或者特性工廠函數嗎?如果這樣做了,那 小姐姐以后又提出一種新屬性的存取邏輯怎么辦?

我們注意到、不管是值不能小于零、還是描述不能為空, 二者的存取邏輯都在 set 方法上,對于 get 方法幾乎沒有邏輯驗證。

那么我們為什么不寫一個 描述符類 、其實現了通用的 __get__ 方法,再設置一個抽象的驗證方法、新來的描述符類只需要繼承該抽象類,再覆蓋該驗證方法即可。這樣能夠極大的節省代碼冗余。

這種思想通常被稱為模板方法設計模式

實現代碼如下:

            
              
                import
              
               abc



              
                class
              
              
                AutoStorage
              
              
                :
              
              
                def
              
              
                __init__
              
              
                (
              
              self
              
                ,
              
               attrname
              
                )
              
              
                :
              
              
        self
              
                .
              
              attrname 
              
                =
              
               attrname

    
              
                def
              
              
                __get__
              
              
                (
              
              self
              
                ,
              
               instance
              
                ,
              
               owner
              
                )
              
              
                :
              
              
                # __get__ 方法除了必要的判斷 instance 是否真實存在以外,操作與之前幾乎一致
              
              
                if
              
               instance 
              
                is
              
              
                None
              
              
                :
              
              
                return
              
               self
        
              
                else
              
              
                :
              
              
                return
              
               instance
              
                .
              
              __dict__
              
                [
              
              self
              
                .
              
              attrname
              
                ]
              
              
                def
              
              
                __set__
              
              
                (
              
              self
              
                ,
              
               instance
              
                ,
              
               value
              
                )
              
              
                :
              
              
                # 1
              
              
        instance
              
                .
              
              __dict__
              
                [
              
              self
              
                .
              
              attrname
              
                ]
              
              
                =
              
               value



              
                class
              
              
                Validated
              
              
                (
              
              abc
              
                .
              
              ABC
              
                ,
              
               AutoStorage
              
                )
              
              
                :
              
              
                # 2
              
              
                def
              
              
                __set__
              
              
                (
              
              self
              
                ,
              
               instance
              
                ,
              
               value
              
                )
              
              
                :
              
              
        value 
              
                =
              
               self
              
                .
              
              validate
              
                (
              
              instance
              
                ,
              
               value
              
                )
              
              
                # 3
              
              
                super
              
              
                (
              
              
                )
              
              
                .
              
              __set__
              
                (
              
              instance
              
                ,
              
               value
              
                )
              
              
                # 4
              
              

    @abc
              
                .
              
              abstractmethod  
    
              
                def
              
              
                validate
              
              
                (
              
              self
              
                ,
              
               instance
              
                ,
              
               value
              
                )
              
              
                :
              
              
                # 5
              
              
                """返回經過驗證的值或拋出異常"""
              
              
                class
              
              
                Quantity
              
              
                (
              
              Validated
              
                )
              
              
                :
              
              
                """驗證值是否大于等于零"""
              
              
                def
              
              
                validate
              
              
                (
              
              self
              
                ,
              
               instance
              
                ,
              
               value
              
                )
              
              
                :
              
              
                # 6
              
              
                if
              
               value 
              
                <
              
              
                0
              
              
                :
              
              
                raise
              
               ValueError
              
                (
              
              
                'value must be > 0'
              
              
                )
              
              
                return
              
               value



              
                class
              
              
                NonBlank
              
              
                (
              
              Validated
              
                )
              
              
                :
              
              
                """驗證字符串是否不為空"""
              
              
                def
              
              
                validate
              
              
                (
              
              self
              
                ,
              
               instance
              
                ,
              
               value
              
                )
              
              
                :
              
              
                # 7
              
              
        value 
              
                =
              
               value
              
                .
              
              strip
              
                (
              
              
                )
              
              
                if
              
              
                len
              
              
                (
              
              value
              
                )
              
              
                ==
              
              
                0
              
              
                :
              
              
                raise
              
               ValueError
              
                (
              
              
                'value cannot be empty or blank'
              
              
                )
              
              
                return
              
               value 

            
          

在上述代碼中:

  1. AutoStorage 描述符類的 set 方法不做任何驗證。
  2. Validated 不但 繼承了 AutoStorage 描述符類 而且還是一個抽象類。
  3. 重寫了 __set__ magic 方法 ,并將 value 設為經過 validate 方法驗證過的值。
  4. 經過 驗證后的 value 可以直接委托給父類 AutoStorage 描述符類直接存儲了
  5. 設置 validate 方法為抽象方法、 其由子類來覆蓋它
  6. Quantity 描述符類重寫了 validate 方法, 驗證值是否大于零。
  7. NonBlank 描述分類重寫了 validate 方法, 驗證值是否為空。

如此一來 Fruits 類的方法體中,只需要增加一行代碼即可:

            
              
                class
              
              
                Fruits
              
              
                :
              
              
    description 
              
                =
              
               NonBlank
              
                (
              
              
                "description"
              
              
                )
              
              
    weight 
              
                =
              
               Quantity
              
                (
              
              
                "weight"
              
              
                )
              
              
    price 
              
                =
              
               Quantity
              
                (
              
              
                "price"
              
              
                )
              
              
                def
              
              
                __init__
              
              
                (
              
              self
              
                ,
              
               price
              
                ,
              
               weight
              
                ,
              
               description
              
                )
              
              
                :
              
              
                # 水果的描述
              
              
        self
              
                .
              
              description 
              
                =
              
               description
        
              
                # 水果的價格
              
              
        self
              
                .
              
              price 
              
                =
              
               price
        
              
                # 水果的重量
              
              
        self
              
                .
              
              weight 
              
                =
              
               weight

    
              
                def
              
              
                subtotal
              
              
                (
              
              self
              
                )
              
              
                :
              
              
                # 小記
              
              
                return
              
               self
              
                .
              
              price 
              
                *
              
               self
              
                .
              
              weight

            
          

上述的諸多描述符類通常放在單獨的 model 模塊中,以供多個模塊共同使用。

例如,產品經理小姐姐有一天和你說,甲方也想賣酸奶,需要給酸奶寫一個類; 那么此時 model 模塊中的 NonBlank 和 Quantity 也能夠提供給酸奶類使用了。

這就是設計模式的魔力,其能夠減少大量的代碼冗余

若我們將諸多描述符類放在單獨的 model 模塊中、那么 Fruits 代碼看起來會是這樣:

            
              
                import
              
               de_model 
              
                as
              
               model

              
                class
              
              
                Fruits
              
              
                :
              
              
    description 
              
                =
              
               model
              
                .
              
              NonBlank
              
                (
              
              
                "description"
              
              
                )
              
              
    weight 
              
                =
              
               model
              
                .
              
              Quantity
              
                (
              
              
                "weight"
              
              
                )
              
              
    price 
              
                =
              
               model
              
                .
              
              Quantity
              
                (
              
              
                "price"
              
              
                )
              
              
                .
              
              
                .
              
              
                .
              
               以下省略 
              
                .
              
              
                .
              
              
                .
              
            
          

如果你學過 Django,那么你會意識到這和 Django ORM 中的 models.TextField() 用法一致。其實 Django 的 models.TextField() 就是通過屬性描述符來實現的。

models.TextField() 不需要傳入托管屬性名。 其原理是類裝飾器 ,我會在后幾篇博文中提到。

總結

使用 python 特性能夠很好的管理需要特殊存儲邏輯的實例屬性。

但是、當大量的屬性都需要同樣的存儲邏輯時、單純的使用 property 依舊會引起代碼冗余。
此時、應該考慮是使用屬性描述符還是實現特性工廠函數 來解決這個問題。

我給出的建議是:在這種情況下, 盡量使用屬性描述符、因為你不知道后續會不會有類似但又不同的屬性存取邏輯。 (例如本博文中的 description 和 weight)

使用屬性描述符比之特性工廠有著很大的優勢、因為其是類,可以實現眾多的面向對象的設計模式。

你可能已經注意到,在本博文中,對于 property 的描述,從來都是 一種 屬性描述符。那么,**除了本博文描述的屬性描述符,還有其他類型的屬性描述符嗎?它們又擁有怎樣的特性?**下一篇博文將會解答此問題。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 永安市| 厦门市| 青海省| 宁南县| 临安市| 文昌市| 富源县| 镇康县| 云霄县| 阿拉尔市| 扎鲁特旗| 基隆市| 安丘市| 正定县| 全州县| 阿荣旗| 治县。| 岫岩| 拜泉县| 博爱县| 汉中市| 义乌市| 隆林| 塘沽区| 永和县| 衡阳县| 贡山| 启东市| 凤阳县| 盘山县| 闽清县| 汨罗市| 扎兰屯市| 沛县| 大化| 乌拉特中旗| 新安县| 剑河县| 宁远县| 辰溪县| 竹溪县|