首頁 > 軟體

Python深入分析@property裝飾器的應用

2022-07-21 14:02:39

什麼是property

簡單地說就是一個類裡面的方法一旦被@property裝飾,就可以像呼叫屬性一樣地去呼叫這個方法,它能夠簡化呼叫者獲取資料的流程,而且不用擔心將屬性暴露出來,有人對其進行賦值操作(避免使用者的不合理操作)。需要注意的兩點是

  • 呼叫被裝飾方法的時候是不用加括號的
  • 方法定義的時候有且只能有self一個引數
>>> class Goods():
        def __init__(self,unit_price,weight):
            self.unit_price = unit_price
            self.weight = weight
        @property
        def price(self):
            return self.unit_price * self.weight
>>> lemons = Goods(7,4)
>>>
>>> lemons.price
28

上面通過呼叫屬性的方式直接呼叫到 price 方法,property把複雜的處理過程封裝到了方法裡面去,取值的時候呼叫相應的方法名即可。

property屬性定義的兩種方式

A、裝飾器方式

在類的方法上應用@property裝飾器,即上面那種方式。

B、類屬性方式

建立一個範例物件賦值給類屬性

>>> class Lemons():
        def __init__(self,unit_price=7):
            self.unit_price = unit_price
        def get_unit_price(self):
            return self.unit_price
        def set_unit_price(self,new_unit_price):
            self.unit_price = new_unit_price
        def del_unit_price(self):
            del self.unit_price
        x = property(get_unit_price, set_unit_price, del_unit_price)
>>> fruit = Lemons()
>>> 
>>> fruit.x                         #呼叫 fruit.x 觸發 get_unit_price
7
>>> 
>>> fruit.x = 9                     #呼叫 fruit.x = 9 觸發 set_unit_price
>>> 
>>> fruit.x
9
>>> 
>>> fruit.unit_price                #呼叫 fruit.unit_price 觸發 get_unit_price
9
>>> del fruit.x                     #呼叫 del fruit.x 觸發 del_unit_price 
>>> 
>>> fruit.unit_price
Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    l.unit_price
AttributeError: 'Lemons' object has no attribute 'unit_price'

property方法可以接收四個引數

  • 第一個引數是獲得屬性的方法名,呼叫 物件.屬性時自動觸發
  • 第二個引數是設定屬性的方法名, 給屬性賦值時自動觸發
  • 第三個引數是刪除屬性的方法名,刪除屬性時自動觸發
  • 第四個引數是字串,是屬性的描述檔案,呼叫物件.屬性.doc時觸發

@property屬性值的限制

在繫結屬性時,如果我們直接把屬性暴露出去,雖然寫起來很簡單,但是,沒辦法檢查引數,導致可以把屬性值隨便改

class Person(object):
    pass
p = Person()
p.age = 1000

我們可以看到類中的屬性被隨意修改,很明顯不能這樣操作,為了限制age的範圍,可以通過一個 set_age()方法來設定成績,再通過一個 get_age() 來獲取年齡,這樣,在 set_score() 方法裡,就可以檢查引數

# -*- coding: utf-8 -*-
class Person(object):
    # score屬性的值 限制範圍為:0-88
    def get_age(self):
        return self.__age
    def set_age(self, value):
        if 0 <= value <= 88:
            self.__age = value
        else:
            self.__age = 0  # 給age一個初始值0
            raise ValueError('age的值必須在0-88之間')  # 自動拋異常
if __name__ == '__main__':
    p = Person()
    p.set_age(100)
    p.get_age()

ValueError('age的值必須在0-88之間')

我們發現,當我們設定限定age的範圍的時候,超過對應的範圍set_age設定值時raise方法會自動給我們丟擲異常,但是上面的方法太過於複雜,所以引入我們的一個裝飾器,裝飾器是可以給函數動態加上功能。對於類的方法,裝飾器一樣起作用。Python內建的 @property 裝飾器就是負責把一個方法變成屬性呼叫的

# -*- coding: utf-8 -*-
class Person(object):
    # score屬性的值 限制範圍為:0-88
    @property  # 把 age 屬性暴露出去
    def age(self):
        return self.__age
    @age.setter  # 當前 age 屬性可以允許賦值
    def age(self, value):
        if 0 <= value <= 88:
            self.__age = value
        else:
            self.__age = 0  # 給age一個初始值0
            raise ValueError('age的值必須在0-88之間')  # 自動拋異常
    @property
    def name(self):
        self.__name = '張三'
        return self.__name
if __name__ == '__main__':
    p = Person()
    p.age = 18
    print(p.age)  # age屬性可以讀,可以寫
    print(p.name)  # name 唯讀屬性

@property 的實現比較複雜,先觀察使用。

把一個getter方法變成屬性,只需要加上 @property 就可以了,此時, @property 本身又建立了另一個裝飾器 @age.setter ,負責把一個setter方法變成屬性賦值,於是,我們就擁有一個可控的屬性操作.

到此這篇關於Python深入分析@property裝飾器的應用的文章就介紹到這了,更多相關Python @property裝飾器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com