這個章節大部分人都明白@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方法返回的屬性要在前面加個"_"
3.@property 是針對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