使用 @property

在使用 @property 之前,让我们先来看一个简单的例子:

  1. class Exam(object):
  2. def __init__(self, score):
  3. self._score = score
  4. def get_score(self):
  5. return self._score
  6. def set_score(self, val):
  7. if val < 0:
  8. self._score = 0
  9. elif val > 100:
  10. self._score = 100
  11. else:
  12. self._score = val
  13. >>> e = Exam(60)
  14. >>> e.get_score()
  15. 60
  16. >>> e.set_score(70)
  17. >>> e.get_score()
  18. 70

在上面,我们定义了一个 Exam 类,为了避免直接对 _score 属性操作,我们提供了 get_score 和 set_score 方法,这样起到了封装的作用,把一些不想对外公开的属性隐蔽起来,而只是提供方法给用户操作,在方法里面,我们可以检查参数的合理性等。

这样做没什么问题,但是我们有更简单的方式来做这件事,Python 提供了 property 装饰器,被装饰的方法,我们可以将其『当作』属性来用,看下面的例子:

  1. class Exam(object):
  2. def __init__(self, score):
  3. self._score = score
  4. @property
  5. def score(self):
  6. return self._score
  7. @score.setter
  8. def score(self, val):
  9. if val < 0:
  10. self._score = 0
  11. elif val > 100:
  12. self._score = 100
  13. else:
  14. self._score = val
  15. >>> e = Exam(60)
  16. >>> e.score
  17. 60
  18. >>> e.score = 90
  19. >>> e.score
  20. 90
  21. >>> e.score = 200
  22. >>> e.score
  23. 100

在上面,我们给方法 score 加上了 @property,于是我们可以把 score 当成一个属性来用,此时,又会创建一个新的装饰器 score.setter,它可以把被装饰的方法变成属性来赋值。

另外,我们也不一定要使用 score.setter 这个装饰器,这时 score 就变成一个只读属性了:

  1. class Exam(object):
  2. def __init__(self, score):
  3. self._score = score
  4. @property
  5. def score(self):
  6. return self._score
  7. >>> e = Exam(60)
  8. >>> e.score
  9. 60
  10. >>> e.score = 200 # score 是只读属性,不能设置值
  11. ---------------------------------------------------------------------------
  12. AttributeError Traceback (most recent call last)
  13. <ipython-input-676-b0515304f6e0> in <module>()
  14. ----> 1 e.score = 200
  15. AttributeError: can't set attribute

小结

  • @property 把方法『变成』了属性。