python property

class property([fget[, fset[, fdel[, doc]]]])
# fget是用于获取属性值的函数
# fset是用于设置属性值的函数
# fdel是用于删除属性值的函数
# doc是文档字符串

下面是官方文档上的一个例子:

In [2]: class C:
        def __init__(self):
            print("invoke __init__")
            self._x = None

        def getx(self):
            print("invoke getx")
            return self._x

        def setx(self, value):
            print("invoke setx")
            self._x = value

        def delx(self):
            print("invoke delx")
            del self._x

        x = property(getx, setx, delx, "I'm the 'x' property.")

当访问c.x时会调用getx方法,当为c.x设置值时会调用setx方法,删除c.x时会调用delx方法。


在对实例属性的获取和设定上,我们希望增加一些额外的处理过程(比如类型检查或者验证)。要自定义对属性的访问,一种简单的方式是将其定义为property。比如下面的代码定义了一个property,增加了对属性的类型检查。

In [9]: class Person:
        def __init__(self, first_name):
            self.first_name = first_name
            print("invoke __init__")
        @property
        def first_name(self):
            print("invoke get first_name")
            return self._first_name
        @first_name.setter
        def first_name(self, value):
            print("invoke set first_name")
            if not isinstance(value, str):
                raise TypeError("Expected a string")
            self._first_name = value
        @first_name.deleter
        def first_name(self):
            raise AttributeError("Can't delete attribute")

你可能会问为什么在init方法中设定的是self.first_name而 不是self._first_name?在这个例子中,property的全部意义就在于我们设置属性时可以执行类型检查。因此,你也想让这种类型检查在初始化的时候也可以进行。所以,在init中设置self.first_name,实际上会调用到setter方法(因此就会跳过self.first_name而去访问self._first_name)。 property使用场景: 只有当确定需要在访问属性必完成一些额外的处理任务时,才应该使用property.


Ref: 1.官方文档 2.python cookbook