开发者社区> 问答> 正文

创建可管理的属性

你想给某个实例attribute增加除访问与修改之外的其他处理逻辑,比如类型检查或合法性验证。

展开
收起
哦哦喔 2020-04-17 15:02:02 800 0
1 条回答
写回答
取消 提交回答
  • 自定义某个属性的一种简单方法是将它定义为一个property。 例如,下面的代码定义了一个property,增加对一个属性简单的类型检查:
    
    class Person:
        def __init__(self, first_name):
            self.first_name = first_name
    
        # Getter function
        @property
        def first_name(self):
            return self._first_name
    
        # Setter function
        @first_name.setter
        def first_name(self, value):
            if not isinstance(value, str):
                raise TypeError('Expected a string')
            self._first_name = value
    
        # Deleter function (optional)
        @first_name.deleter
        def first_name(self):
            raise AttributeError("Can't delete attribute")
    上述代码中有三个相关联的方法,这三个方法的名字都必须一样。 第一个方法是一个 getter 函数,它使得 first_name 成为一个属性。 其他两个方法给 first_name 属性添加了 setter 和 deleter 函数。 需要强调的是只有在 first_name 属性被创建后, 后面的两个装饰器 @first_name.setter 和 @first_name.deleter 才能被定义。
    
    property的一个关键特征是它看上去跟普通的attribute没什么两样, 但是访问它的时候会自动触发 getter 、setter 和 deleter 方法。例如:
    
    >>> a = Person('Guido')
    >>> a.first_name # Calls the getter
    'Guido'
    >>> a.first_name = 42 # Calls the setter
    Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "prop.py", line 14, in first_name
            raise TypeError('Expected a string')
    TypeError: Expected a string
    >>> del a.first_name
    Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
    AttributeError: can`t delete attribute
    >>>
    在实现一个property的时候,底层数据(如果有的话)仍然需要存储在某个地方。 因此,在get和set方法中,你会看到对 _first_name 属性的操作,这也是实际数据保存的地方。 另外,你可能还会问为什么 __init__() 方法中设置了 self.first_name 而不是 self._first_name 。 在这个例子中,我们创建一个property的目的就是在设置attribute的时候进行检查。 因此,你可能想在初始化的时候也进行这种类型检查。通过设置 self.first_name ,自动调用 setter 方法, 这个方法里面会进行参数的检查,否则就是直接访问 self._first_name 了。
    
    还能在已存在的get和set方法基础上定义property。例如:
    
    class Person:
        def __init__(self, first_name):
            self.set_first_name(first_name)
    
        # Getter function
        def get_first_name(self):
            return self._first_name
    
        # Setter function
        def set_first_name(self, value):
            if not isinstance(value, str):
                raise TypeError('Expected a string')
            self._first_name = value
    
        # Deleter function (optional)
        def del_first_name(self):
            raise AttributeError("Can't delete attribute")
    
        # Make a property from existing get/set methods
        name = property(get_first_name, set_first_name, del_first_name)
    
    2020-04-17 15:02:17
    赞同 展开评论 打赏
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载