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

欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

淺析 python 屬性描述符(上)

系統(tǒng) 1756 0

轉(zhuǎn)載自我自己的 github 博客 ——> 半天鐘的博客

元編程相關(guān)博文的目錄及鏈接

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

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

Review

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

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

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

當重復(fù)為 weight 和 price 編寫幾乎相同的代碼時, 重構(gòu)代碼的時機到了!!!

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

博文的編寫思路

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

然后、我會仔細的說明 實現(xiàn)屬性描述符需要注意的細節(jié) 屬性描述符的性質(zhì) 及其如何與托管類實例交互。

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

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

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

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

            
              
                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 類進行了重構(gòu),使用了 Quantity 實例作為 Fruits 類的 weight 和 price 的類屬性值。

可以看到、 重構(gòu)后的 Fruits 類實例有如下行為

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

如果你不明白這些行為的原理,沒關(guān)系,我會在下一小節(jié)解釋屬性描述符的原理,現(xiàn)在你只需要知道,重構(gòu)后的代碼有著這樣的行為。

重構(gòu)后的好處

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

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

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

屬性描述符原理

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

專有名詞

描述符類

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

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

托管類

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

描述符實例

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

托管實例

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

托管屬性

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

存儲屬性

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

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

描述符類與托管類的關(guān)系

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

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

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

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

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

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

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

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

描述符實例如何工作

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

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

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

property 是一種屬性描述符

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

property 類實現(xiàn)了完整的描述符協(xié)議

            
              
                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 類的構(gòu)造方法返回一個描述符實例,該實例的 __get__ magic方法即是get_weight、 __set__ magic 方法既是 set_weight。

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

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

代碼來自《流暢的 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") 就可以轉(zhuǎn)變?yōu)? weight = quantity('weight') 。甚至比創(chuàng)建 Quantity 類的代碼還要短。

但是,對于描述符類來說、依舊有著得天獨厚的優(yōu)勢, 即面向?qū)ο蟮姆绞?

描述符類能夠繼承

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

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

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

那么我們?yōu)槭裁床粚懸粋€ 描述符類 、其實現(xiàn)了通用的 __get__ 方法,再設(shè)置一個抽象的驗證方法、新來的描述符類只需要繼承該抽象類,再覆蓋該驗證方法即可。這樣能夠極大的節(jié)省代碼冗余。

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

實現(xiàn)代碼如下:

            
              
                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
              
              
                """返回經(jīng)過驗證的值或拋出異常"""
              
              
                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 設(shè)為經(jīng)過 validate 方法驗證過的值。
  4. 經(jīng)過 驗證后的 value 可以直接委托給父類 AutoStorage 描述符類直接存儲了
  5. 設(shè)置 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 模塊中,以供多個模塊共同使用。

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

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

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

            
              
                import
              
               de_model 
              
                as
              
               model

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

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

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

總結(jié)

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

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

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

使用屬性描述符比之特性工廠有著很大的優(yōu)勢、因為其是類,可以實現(xiàn)眾多的面向?qū)ο蟮脑O(shè)計模式。

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


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

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

【本文對您有幫助就好】

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

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 两性视频在线 | 日本三级香港三级乳网址 | 野外性xxxxfrxxxx | 两性午夜视频 | 亚洲国产婷婷香蕉久久久久久99 | 亚洲国产精品人人爽夜夜爽 | 国内精品玖玖玖玖电影院 | 亚洲在线观看免费视频 | 欧美激情亚洲激情 | 日日草夜夜操 | 免费在线一区二区 | 91丁香亚洲综合社区 | 一级特黄视频 | 91看点| 精品二区 | 中文精品久久 | 日本大学生免费一级一片 | 狠狠狠狠狠狠 | 性色在线| 欧美精品免费看 | 亚洲欧美日韩激情在线观看 | 精品国产久 | 国产激情久久久久久熟女老人AV | 無码一区中文字幕少妇熟女H | 一区二区三区国产免费 | 久久精品小视频 | 色综合天天综一个色天天综合网 | 精品免费久久久久久成人影院 | 久久久精品午夜免费不卡 | 在线观看日本污污ww网站 | 性色成人网 | 91精品电影| 视频在线观看一区 | 日韩国产欧美视频 | 男人添女人下面免费网站 | 综合第一页 | 香蕉视频免费网站 | 日韩中文字幕一区 | 午夜性啪啪A片免费播放 | 亚洲欧美视频 | 久久综合日韩亚洲精品色 |