1. 程式人生 > >python3:聊聊 為什麼要有@property裝飾器

python3:聊聊 為什麼要有@property裝飾器

這個章節大部分人都明白@property 的作用。
難道不是把方法轉化成屬性,可以直接賦值?

那我們說說為什麼這麼做有什麼意義呢?

先用程式碼一點點引導。
1.避免直接賦值,繞過校驗

class Student:
    def __init__(self,name,age):
        self.name=name
        self.age=age


stu=Student("Lady",50)
prtint(stu.age)
stu.age=120
print(stu.age)

列印結果:

50
120

從上邊結果看,可以隨意讀取和修改age並且設定的age還不符合年齡規範。
這顯然不行。
首先我們想到的是 用方法加校驗 並建立屬性,並用方法獲取。

class Student:
    def __init__(self,name):
        self.name=name
    def set_age(self,age):
        if isinstance(age,int):
            if 0<age<120:
                self.age=age
        else:
            print("請輸入合法的年齡")
    def get_age(self):
        return self.age


stu=Student("Lady")
stu.age=120
print(stu.age)

列印結果;

120

上邊的程式碼小夥伴該說了,我不用方法也可以修改值,
stu.age=120
print(stu.age)
並沒有報錯呀。

為了解釋這個原因,我們直接列印這個屬性。

print(stu.age)

報錯如下:

 'Student' object has no attribute 'age'

之所以不會報錯 關鍵點在 stu.age=120 這個步驟是例項化物件。
stu自己給自己添加了一個age 屬性,所以不會報錯。
這個屬性只是屬於stu,你換個例項再列印也一定會報錯。扯的有點多了,
開始回到正軌。

class Student:
    def __init__(self,name):
        self.name=name
    def set_age(self,age):
        if isinstance(age,int):
            if 0<age<120:
                self.age=age
            else:
                print("請注意你的年齡範圍")
        else:
            print("請輸入合法的年齡")
    def get_age(self):
        return self.age


stu=Student("Lady")
stu.set_age(1110)    #輸入不規範的年齡
stu.set_age(10)      #設定age,並通過一系列的校驗
print(stu.age)       # 可以直接呼叫
print(stu.get_age())  #獲取age

列印結果 :

請注意你的年齡範圍
10
10

兩種方法都可以取到age,
那小夥伴該說 我們就沒有必要寫get方法了,直接用stu.age呼叫就行了
(直接用了set 方法的返回值)

為了防止這種情況發生,規範如下;
set方法裡面的返回的屬性名前面加上 _,一個小短線。
(實際也不能避免,相對而言安全)
所以寫成這樣

class Student:
    def __init__(self,name):
        self.name=name
    def set_age(self,age):
        if isinstance(age,int):
            if 0<age<120:
                self._age=age
            else:
                print("請注意你的年齡範圍")
        else:
            print("請輸入合法的年齡")
    def get_age(self):
        return self._age


stu=Student("Lady")
stu.set_age(1110)    #輸入不規範的年齡
stu.set_age(10)      #設定age,並通過一系列的校驗
print(stu.get_age())  #獲取age

這樣就可以了了 。
2.應用@property 可以把呼叫的方法像呼叫屬性一樣直接用。

Python內建的@property裝飾器就是負責把一個方法變成屬性呼叫的:

class Student:
    def __init__(self,name):
        self.name=name

    @property
    def age(self):
        return self._age
    @age.setter
    def age(self,age):
        if isinstance(age,int):
            if 0<age<120:
                self._age=age
            else:
                print("請注意你的年齡範圍")
        else:
            print("請輸入合法的年齡")



stu=Student("Lady")

stu.age=10   #設定age,並通過一系列的校驗
print(stu.age)  #獲取age

上邊主要以下幾點:
1.get 和set 的方法名稱都要一樣(age)
2.set方法返回的屬性要在前面加個"_"
[email protected] 是針對get方法
[email protected] 是針對set 方法,是@property本身又建立了另一個裝飾器
5.直接可以這樣stu.age=10 物件名.方法名進行賦值,
6.只定義getter方法,不定義setter方法是一個只讀屬性
下邊介紹這個特性。

3.只定義getter方法,不定義setter方法就是一個只讀屬性

class Student:
    def __init__(self,name):
        self.name=name

    @property
    def age(self):
        return self._age
    @age.setter
    def age(self,age):
        if isinstance(age,int):
            if 0<age<120:
                self._age=age
            else:
                print("請注意你的年齡範圍")
        else:
            print("請輸入合法的年齡")
    @property
    def after_3(self):
        return self._age+3


stu=Student("Lady")

stu.age=10   #設定age,並通過一系列的校驗
print(stu.age)  #獲取age
stu.after_3=5

列印結果:

AttributeError: can't set attribute

但是我們可以讀取 :

print(stu.after_3)

列印結果:

13