property

在面向对象编程中,我们经常需要对对象的属性进行访问和修改,但是直接访问和修改对象的属性可能会导致一些问题,比如无法对参数进行检查,这样就可以随意修改对象的属性,比如下面的例子:

s = Student("Tom")
s.score = 999

这显然不合逻辑,为了限制 score 的范围,我们可以通过一个 set_score() 方法来设置成绩,再通过一个 get_score() 来获取成绩,这样,在 set_score() 方法里,就可以检查参数

class Student():
  def get_score(self):
    return self._score

  def set_core(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
前面我们提到的 getter,setter方法,现在对 Student 实例进行操作,就不能随意更改 score 了.

现在,对任意的 Student 实例进行操作,就不嫩个随心所欲地设置 score 了.

s = Student()
s.set_core(33)
print(s.get_score())
s.set_core(1111) # ValueError: score must between 0-100

在 Python 中我们有更简单的方式来实现上面的功能,那就是使用@property 装饰器,该装饰器可以把一个方法编程属性调用:

class Student():
  @property
  def score(self):
    return self._score

  @score.setter
  def 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
我们只需要在一个 getter 方法上加上@property 装饰器就可以把一个方法变成属性调用,比如上面的 score 方法,我们可以通过 s.score 来获取 score 属性了,而不是通过 s.get_score() 方法,这样就可以更加方便的访问属性了

另外当我们将方法编程属性调用后,@property 本身又会创还能另一个装饰器@score.setter ,负责把一个 setter 方法变成属性赋值,这样我们就可以来定制 setter 方法了,比如上面的例子

上面 我们将 score 方法转变成属性后,然后就可以通过 @score.setter 的装饰器来定义 setter 方法,这样我们就可以直接修改 score 属性了.而不是通过s.set_score(80) 方法,这样就更加方便了

s = Student()
s.score = 22
print(s.score)
s.score = 666
print(s.score)

如果我们只定义了getter 方法,不定义setter 方法,那么这个属性就是只读属性,不能修改,比如下面的例子:

class Student():
  @property
  def score(self):
    return self._score

  @score.setter
  def 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

  @property
  def birth(self):
    return self._birth

  @birth.setter
  def birth(self, value):
    self._birth = value

  @property
  def age(self):
    return self._age

s = Student()
s.score = 22
print(s.score)

s.birth = 111
print(s.birth)

s.age = 12 # AttributeError: property 'age' of 'Student' object has no setter
print(s.age)
回到页面顶部