現(xiàn)在試想一下我們有一個(gè)這樣的場(chǎng)景。
class Person:
def __init__(self, name, gender):
self.name = name
self.gender = gender
我們希望在這里加入類型檢查,name和gender都必須為字符串。
熟悉python的同學(xué)當(dāng)然想到了property。那我們的代碼就變成了這樣子。
class Person:
def __init__(self, name, gender):
self.name = name
self.gender = gender
@property
def name(self):
return self._name
@name.setter
def name(self, name):
if isinstance(name, str):
self._name = name
else:
raise AttributeError('name must be a string !')
@property
def gender(self):
return self._gender
@gender.setter
def gender(self, gender):
if isinstance(gender, int):
self._gender = gender
else:
raise AttributeError('gender must be a string !')
有沒有發(fā)現(xiàn)一個(gè)很嚴(yán)重的問題,我們寫了重復(fù)的邏輯,這樣做是個(gè)十分不好的設(shè)計(jì)。我們希望自己寫的類似于類型檢查的邏輯可以復(fù)用。
下面就該我們描述符出場(chǎng)了,我們的代碼變?yōu)榱讼旅孢@樣子。
class StringField:
def __get__(self, instance, owner):
return self.data
def __set__(self, instance, value):
if not isinstance(value, str):
raise ValueError('need string !')
self.data = value
def __delete__(self):
...
class Person:
name = StringField()
gender = StringField()
if __name__ == '__main__':
p = Person()
p.name = 'Tom'
print(p.name)
p.name = 123
我們看一下輸出結(jié)果。
Tom
Traceback (most recent call last): File "/Users/shizhentao/PythonProjects/flask-demo/test.py", line 30, in <module>
p.name = 123 File "/Users/shizhentao/PythonProjects/flask-demo/test.py", line 8, in __set__
raise ValueError('need string !')
ValueError: need string !
跟上面的代碼實(shí)現(xiàn)的效果一樣,但是我們實(shí)現(xiàn)的十分精簡(jiǎn)。