美文网首页
Python3 - 创建可管理的属性

Python3 - 创建可管理的属性

作者: 惑也 | 来源:发表于2018-12-25 14:25 被阅读21次

问题

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

解决方案

自定义某个属性的一种简单方法是将它定义为一个property。 例如,下面的代码定义了一个property,增加对一个属性简单的类型检查:

class Person(object):
    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('Exception 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('Xingzhe')   

print(a)
<__main__.Person object at 0x1085d93c8>

print(a.first_name)
Xingzhe

a.first_name = 42
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的时候,底层数据(如果有的话)仍然需要存储在某个地方。 因此,在getset方法中,会有对 _first_name 属性的操作,这也是实际数据保存的地方。

另外, __init__() 方法中设置了 self.first_name 而不是 self._first_name,因为本示例中创建property的目的就是在设置attribute的时候进行检查。通过设置 self.first_name ,会自动调用 setter 方法,进行参数的检查。

讨论

一个property属性,其实就是(绑定)一系列相关方法的集合。查看拥有property的类, 会发现property本身的fget、fset和fdel属性就是类里面的普通方法。比如:

print(Person.first_name.fget)
print(Person.first_name.fset)
print(Person.first_name.fdel)

<function Person.first_name at 0x1021f8510>
<function Person.first_name at 0x1021f8598>
<function Person.first_name at 0x1021f8620>

通常来讲,不需要直接取调用fget或者fset,它们会在访问property的时候自动被触发。

只有当确实需要对attribute执行其他额外的逻辑操作时,才应该使用到property。

property还是一种定义动态计算attribute的方法。 这种类型的attributes并不会被实际的存储,而是在需要的时候才进行计算。比如:

import math

class Circle(object):
    def __init__(self, radius):
        self.radius = radius

    @property
    def area(self):
        return math.pi * self.radius ** 2

    @property
    def diameter(self):
        return self.radius * 2

    @property
    def permeter(self):
        return 2 * math.pi * self.radius

通过使用多个property,将所有的访问接口形式统一起来,可以实现优雅的编程接口。对半径、直径、周长和面积的访问都是通过属性访问,就跟访问普通的attribute一样。 如果不这样做的话,就需要在代码中混合使用普通属性访问和方法调用。 下面是使用的实例:

c = Circle(4.0)
print(c.radius)
4.0

print(c.area)
50.26548245743669

print(c.diameter)
8.0

print(c.permeter)
25.132741228718345

相关文章

  • Python3 - 创建可管理的属性

    问题 给某个实例attribute,增加除访问与修改之外的其他处理逻辑,比如类型检查或合法性验证。 解决方案 自定...

  • python 创建可管理的属性-property使用

    对实例属性的获取和访问,我们希望增加一些额外的处理过程,比如说检查类型或者验证。要定义对属性的访问,一种简单的方式...

  • Django-19 admin后台管理

    admin配置步骤 创建后台管理账户 - 该账号为管理后台最高权限账号python3 manage.py crea...

  • Python3之进程池

    在 Python3 中,我们可以通过创建一个进程池对象来管理运行不同任务的进程。 class multiproce...

  • mac python3虚拟环境--virtualenv安装步骤

    安装python3 brew install python3 创建虚拟环境 virtualenv -ppython...

  • UIView与CALayer区别

    创建UIView对象时,UIView内部会自动创建一个层(CALayer对象),通过UIView的layer属性可...

  • Neo4j-1.1 CQL-CREATE命令

    创建没有属性的节点 使用属性创建节点 在没有属性的节点之间创建关系 使用属性创建节点之间的关系 为节点或者关系创建...

  • 美多商城

    忽略.idea cd 到工程目录 创建python3 的虚拟环境 mkvirtualenv -p python3 ...

  • python 创建可类型检查的类属性

    8.9 可以以描述符类的形式定义其功能。 所谓的描述符就是以特殊方法 get set delete 的形式实现了三...

  • 三十:Django之后台管理

    一:本地化 语言和时区的本地化,修改setting.py文件 二:创建管理员 命令:python3 manage....

网友评论

      本文标题:Python3 - 创建可管理的属性

      本文链接:https://www.haomeiwen.com/subject/scfxlqtx.html