@property 和 @xxx.setter 使用

469 阅读2分钟

检查输入的属性值:

>>> class Student(object):
...     def get_score(self):
...             return self._score
...     def set_score(self, value):
...             if not isinstance(value, int):
...                     raise ValueError('score must be an integer!')
...             if value < 0 or value > 100:
...                     raise ValueError('score must between 0 ~ 100!')
...             self._score = value
...
>>> s = Student()
>>> s.set_score(60)
>>> s.get_score()
60
>>> s.set_score(999)          
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in set_score
ValueError: score must between 0 ~ 100!

通过上面的例子可以知道,对socre 值进行了检查,如果不符合,就提示报错信息 不过在书写上显得复杂了点。

使用 @property来简化对score的检查:

>>> class Student(object):
...     @property
...     def score(self):
...             return self._score
...     @score.setter
...     def score(self, value):
...             if not isinstance(value, int):
...                     raise ValueError('score must be an interger!')
...             if value < 0 or value > 100:
...                     raise ValueError('score must between 0~ 100!')
...             self._score = value
...
>>> s = Student()
>>> s.score = 60    #相当于set_score(60)
>>> s.score         #相当于get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 10, in score
ValueError: score must between 0~ 100!
>>>

我们可以注意到 @property,让socre属性不是直接暴露,而是通过 getter 和 setter 方法来实现的。

定义只读属性:

>>> class Student(object):
...     @property
...     def birth(self):
...             return self._birth
...     @birth.setter
...     def birth(self, value):
...             self._birth = value
...     @property
...     def age(self):
...             return 2015 - self._birth
...
>>> s = Student()
>>> s.birth = 1989
>>> s.birth
1989
>>> s.age = 20
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> s.age
26

通过上面可以看到,birth 是可读可写,但 age 是只读属性。

总结:

1、为了安全,我们需要对赋值的属性进行检查
2、为了简化,我们使用@property,把 getter 方法变成属性
3、通过 @property 和 @xxx.setter 来控制属性的读写权限