python 使用 @property

引用-廖雪峰

背景

在设置属性时,可以直接把属性暴露出去,这个简单,但是会导致被随意修改属性值。

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广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。

你可能感兴趣的:(python 使用 @property)