本文介绍一个python常用的装饰器Property,其主要作用就是解决python class的属性的setter和getter,和类属性保护的问题。

首先枷梢我们有一个Student类,其中有一个name的属性。

s = Student()
s.name = 'xuesheng'

但是,因为Python并没有属性保护机制,所以可以通过类实例直接访问name属性[直接把name暴露出去]。同时,我们也没有办法进行属性检测,比如对name我们可能有一些格式要求,在赋值之前需要先检测格式。这显然不合逻辑。所以,我们可以通过一个set_name()方法来设置名字,再通过一个get_name()来获取名字,这样,在set_name()方法里,就可以检查名字。

class Student(object):
    def get_name(self):
         return self._name

    def set_name(self, value):
        if not isinstance(value, str):
            raise ValueError('name must be a string!')
        self._name = value

但是,上面的方法又略显复杂,通过@property方式就可以兼顾。Python内置的@property装饰器就是负责把一个方法变成属性调用的。

class Student(object):
    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        if not isinstance(value, str):
            raise ValueError('name must be a string!')
        self._name = value

把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@name.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作:

s = Student()
s.name = 'xuesheng' #实际就是`set_name('xuesheng')`
s.name #实际调用的是`get_name()`

需要注意的是,即便使用@property也不能防止通过类实例来访问属性,比如上面例子中,s._name依然是合法的。

@property广泛应用在类的定义中,可以让开发者写出简短的代码,同时保证对参数进行基本的保护和必要的检查,这样,程序运行时就减少了出错的可能性。