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