1. 程式人生 > >python - @property屬性

python - @property屬性

總結:
1). Python內建的@property裝飾器就是負責把一個方法變成屬性呼叫的;
2). @property本身又建立了另一個裝飾器@state.setter,負責把一個
setter方法變成屬性賦值,於是,我們就擁有一個可控的屬性操作.
3). @property廣泛應用在類的定義中,可以讓呼叫者寫出簡短的程式碼,
同時保證對引數進行必要的檢查,這樣,程式執行時就減少了出錯的可能性。

現在模擬一個借書系統,規定0是借出,1是未借出。但是若輸入3-100程式不會報錯,會導致借書狀態錯誤。這時利用@property就可以解決這個問題。
設定 get_state獲取狀態、set_state檢查狀態、del_state刪除狀態。

from colorFont import  *
class Book(object):
    def __init__(self, name, kind, state):
        self.name = name
        self.kind = kind
        # 0: 借出  1: "未借出"
        # 書的狀態只能是0或者1, 如果是其他, 應該報錯;
        # 檢視書狀態, 希望是漢字形式, 有實際意義的;
        self.__state  = 0 # 私有屬性

    @property   # 將這個方法轉換為類的屬性; print(book.state)
    def get_state(self):
        if self.__state == 0:
            return  ERRRED + "借出"
        elif self.__state == 1:
            return  OKGREEN + "未借出"
     
    def set_state(self, value):
        # 檢查引數
        if value in (0,1):
            # 更新書狀態
            self.__state = value
        else:
            print(ERRRED + "更新錯誤, 必須是0或者1")

    def del_state(self):
        # 刪除書的狀態
        del self.__state
        print(OKGREEN + "刪除書狀態成功!")

if __name__ == "__main__":
    book = Book("python核心程式設計", 'python', 1)
    book.set_state(3)  # book.state = 3
    print(book.get_state)  # print(book.state)

在這裡插入圖片描述

但是這樣會顯得很繁瑣。@property建立了另一個裝飾器@state.setter負責把一個setter方法變成屬性賦值,於是,我們就擁有一個可控的屬性操作.

from colorFont import  *
class Book(object):
    def __init__(self, name, kind, state):
        self.name = name
        self.kind = kind
        # 0: 借出  1: "未借出"
        # 書的狀態只能是0或者1, 如果是其他, 應該報錯;
        # 檢視書狀態, 希望是漢字形式, 有實際意義的;
        self.__state  = 0 # 私有屬性

    @property   # 將這個方法轉換為類的屬性; print(book.state)
    def state(self):
        if self.__state == 0:
            return  ERRRED + "借出"
        elif self.__state == 1:
            return  OKGREEN + "未借出"

    @state.setter  # book.state = 0
    def state(self, value):
        if value in (0,1):
            # 更新書狀態
            self.__state = value
        else:
            print(ERRRED + "更新錯誤, 必須是0或者1")

    @state.deleter  # del book.state
    def state(self):
        del self.__state
        print(OKGREEN + "刪除書狀態成功!")

if __name__ == "__main__":
    book = Book("python核心程式設計", 'python', 1)
	book.state = 1
    print(book.state)
    del book.state

在這裡插入圖片描述

@property屬性還可以定義只讀屬性(不定義setter方法就是隻讀屬性)
原始碼範例:
可以ctrl進入date,我們可以發現year,month,day都為只讀屬性
在這裡插入圖片描述

from datetime import  date
#from datetime import  time
#import time
# -datetime.date:表示日期的類。常用的屬性有year, month, day;
#-datetime.time:表示時間的類。常用的屬性有hour, minute, second, microsecond;

# Read-only field accessors
@property
def year(self):
    # year (1-9999)
    return self._year


@property
def month(self):
    # month (1-12)
    return self._month


@property
def day(self):
    # day (1-31)
    return self._day


if __name__ == '__main__':
    d = date(2019, 10, 10)
    print(d.year)
    print(d.month)
    print(d.day)

輸出:
在這裡插入圖片描述

為了測試是否d是否只讀,測試函式寫成:

if __name__ == '__main__':
    d = date(2019, 10, 10)
    print(d.year)
    print(d.month)
    print(d.day)


    d.year = 2020     # 此處不成功, year是隻讀的
    del d.year        # 此處不成功, year是隻讀的
    print(d.year)

輸出報錯:

2019
10
10
Traceback (most recent call last):
  File "/home/kiosk/Documents/python/python1230/day13/07_property屬性.py", line 68, in <module>
    d.year = 2020     # 此處不成功, year是隻讀的
AttributeError: attribute 'year' of 'datetime.date' objects is not writable