引用-廖雪峰
背景
在设置属性时,可以直接把属性暴露出去,这个简单,但是会导致被随意修改属性值。
class Student(object):
def __init__(self):
self.score = 60
In [13]: student = Student()
In [15]: student.score
Out[15]: 60
In [16]: student.score=101
In [17]: student.score
Out[17]: 101
为了避免上面值被随意修改,我们可以增加函数去做判断,可以检查属性值是否有效。
class Student(object):
def __init__(self):
self.score = 60
def get_score(self):
return self.score
def set_score(self, value):
if not isinstance(value, int):
raise ValueError('score %s must be an integer!' % value)
if value < 0 or value > 100:
raise ValueError('score %s must between 0 ~ 100!' % value)
self.score = value
In [2]: student = Student()
In [3]: student.score
Out[3]: 60
In [4]: student.get_score()
Out[4]: 60
In [6]: student.set_score(95)
In [7]: student.score
Out[7]: 95
In [8]: student.get_score()
Out[8]: 95
In [9]: student.set_score(9.9)
---------------------------------------------------------------------------
... ...
ValueError: score 9.9 must be an integer!
In [10]: student.set_score(101)
---------------------------------------------------------------------------
... ...
ValueError: score 101 must between 0 ~ 100!
但是,上面的用法比较复杂,python有没有更好的方法去实现这个功能呢? 有, 就是Python内置的@property
装饰器
使用@property
装饰器
class Student(object):
def __init__(self):
self.score = 60
@property
def student_score(self): # student_score 方法名不要和score的属性名一样
return self.score
@student_score.setter
def student_score(self, value):
if not isinstance(value, int):
raise ValueError('score %s must be an integer!' % value)
if value < 0 or value > 100:
raise ValueError('score %s must between 0 ~ 100!' % value)
self.score = value
加上@property
, 把一个getter方法变成属性; @property
本身又创建了另一个装饰器@student_score.setter
,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的(方法变成属性)操作。
In [5]: student = Student()
In [6]: student.score
Out[6]: 60
In [7]: student.student_score
Out[7]: 60
In [8]: student.student_score = 95
In [9]: student.score
Out[9]: 95
In [10]: student.student_score
Out[10]: 95
In [11]: student.student_score = 9.5
---------------------------------------------------------------------------
... ...
ValueError: score 9.5 must be an integer!
In [12]: student.student_score = 101
---------------------------------------------------------------------------
... ...
ValueError: score 101 must between 0 ~ 100!
还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性。
总结
@property
广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。