作用:
将类方法转换为类属性,可以用 对象 . 直接获取属性值或者对属性进行赋值
实现方式:
使用property类来实现,也可以使用property装饰器实现,二者本质是一样的。多数情况下用装饰器实现。
举例:
比如一个学生成绩表定义成这样:
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) # ok!
>>> s.get_score()
60
>>> s.set_score(9999)
Traceback (most recent call last):
...
ValueError: score must between 0 ~ 100!
但是为了方便,们不想写s.set_score(60)啊,直接像类方法赋值那样s.score = 9999不是更快么,加了方法做限制不能让调用的时候变麻烦啊,@property快来帮忙….
class Student(object):
@property
def score(self):
return self._score
@score.setter #相当于setter方法,setter装饰器的写法是刚刚被property的装饰器所装饰的函数的名称,再加上setter属性。
def score(self,value):
if not isinstance(value, int):
raise ValueError('分数必须是整数才行呐')
if value < 0 or value > 100:
raise ValueError('分数必须0-100之间')
self._score = value
我们调用的时候需要这么调用:
>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60)
>>> s.score # OK,实际转化为s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
...
ValueError: score must between 0 ~ 100!
一开始可能不太容易理解,score明明是一个实例方法,内部也没有setter这个属性,为什么就变成了一个装饰器,还有setter这个属性了?
实际上,score()方法上增加@property装饰器,等同于score= property(fget=score),将score赋值为property的实例。
所以,被装饰后的score,已经不是这个实例方法score了,而是property的实例score。
可以将score的type打印出来看看,会得到<class 'property'>,说明score已经不是当初那个score了,他们只是同名而已。
property的另外两个方法getter、deleter也是同理。
还有一个疑惑:
为什么不直接在__init__中用self.score=score或者self.score=self.score()设置并限制对象属性呢,后来想了想,普通的类中的可以这个做,但是在模型类中就不适合这么做了,所以它的存在还是有它的道理 的。