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
现在,对任意的 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
@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)