Python中操作屬性值的辦法有很多爹谭,我將通過四個實例來循序漸進的說明枷邪。
正文:
我們通常要對屬性進行獲取(getter),修改(setter)诺凡,刪除(deleter)這些操作东揣,比如最簡單的可以這樣實現(xiàn):
### 實例1 ###
class Student(object):
pass
student = Student() # 實例化對象
student.name = 'Li' # 添加/設(shè)置 name屬性
student.name = 'Hu' # 修改name屬性
student.name # 取name屬性
'Hu'
del student.name # 刪除name屬性
我們在實例化student對象后,的確很方便的為實例添加了屬性腹泌,但是問題來了嘶卧。很多時候我們是不希望一個對象的屬性被隨意修改的,而且我們希望對象的屬性值是有效的凉袱,但是通過上面方法芥吟,屬性可能接收到任意值。也就是說绑蔫,我們有時需要對屬性的操作進行限制來避免獲取錯誤的屬性值运沦!
為了對屬性的操作進行限制,得到希望的屬性值配深,我們可以在定義類的時候添加一些方法:
### 實例2 ###
class Student(object):
def __init__(self):
self._name = None
def get_name(self): # 取屬性
return self._name
def set_name(self, n): # 修改/設(shè)置 屬性
if not isinstance(n, str): # 如果傳入的不是字符串 拋出一個異常 可以避免屬性接受非字符串對象
raise TypeError('Name must be str!') # raise表達(dá)式用于拋出一個異常
self._name = n
student = Student()
student.set_name('li') # 正確的設(shè)置屬性
student.get_name() # 訪問屬性
li
student.set_name(123) # 錯誤的設(shè)置屬性
TypeError: Name must be str!
這下的確可以限制屬性了携添,但是對于一個Python程序員來說,這還不夠不優(yōu)雅( ̄▽ ̄)"篓叶,因為每次調(diào)用方法顯的有些麻煩烈掠。觀察上面兩個例子羞秤,我們就想:能不能在保證對屬性進行限制的情況下又能像第一個例子中那樣操作屬性呢?Python中的property()函數(shù)滿足了我們的要求:
### 實例3 ###
class Student(object):
def __init__(self):
self._name = None
def get_name(self):
return self._name
def set_name(self, value):
self._name = value
def del_name(self):
del self._name
x = property(get_name,set_name,del_name,"I am the 'x' property.")
student = Student() # 實例化
student.x = 'Li' # 相當(dāng)于 student.set_name('Li')
student.x # 相當(dāng)于 student.get_name
'Li'
del tudent.x # 相當(dāng)于 del student.name
在上面的代碼中property函數(shù)的原型是:property([fget[, fset[, fdel[, doc]]]])
左敌,它將返回新式類屬性瘾蛋。當(dāng)使用student.x = 'Li'
,相當(dāng)于 student.set_name('Li')
矫限;當(dāng)使用student.x
哺哼,相當(dāng)于 student.get_name
;當(dāng)使用del tudent.x
叼风,相當(dāng)于del student.name
取董。
這下可以了吧?還沒无宿,利用Python中的裝飾器可以讓我們把上述的代碼寫的更加簡單:
### 實例4 ###
class Student(object):
def __init__(self):
self._name = None
@property
def name(self): # 注意 這三個方法名要一樣
return self._name
@name.setter # 注意 裝飾器名改變
def name(self, value): # 注意 這三個方法名要一樣
self._name = value
@name.deleter # 注意 裝飾器名改變
def name(self): # 注意 這三個方法名要一樣
del self._name
student = Student()
student.name = 'Li' # 相當(dāng)于 student.set_name('Li')
student.name # 相當(dāng)于 student.get_name
'Li'
del student.name # 相當(dāng)于 del student.name
總結(jié):
- 操作屬性的方法通常包含最基礎(chǔ)的三個:獲取(get)茵汰,修改(set),刪除(del)孽鸡。
- 可以像操作普遍變量一樣操作屬性蹂午。這樣雖然方便,但是可能會導(dǎo)致屬性被隨意修改彬碱,以及接受一些不正常的值豆胸。
- 為避免屬性被隨意修改,我們可以在定義類時順便定義方法巷疼,通過方法實現(xiàn)屬性的獲取配乱、修改和刪除。
- 在定義類中使用property函數(shù)可以使得限制屬性的同時能夠簡單的操作它們皮迟。使用@property語句可以進一步簡化代碼。
- python簡潔設(shè)計的風(fēng)格從操作屬性這樣一個問題中也可見一斑桑寨!