这里主要是说明一下描述器的应用,python提供了一个property的描述器,常用于做装饰器。但是如果在一个应用场景中对于某类型的属性都需要做相同的处理的时候就需要写很多的property,这时候如果能自定义描述器就可以简便处理。下面就分别讲自定义的描述器和实际的应用以及property的应用和原理。
自定义描述器
从上面一节可以看到我们给出了一个用于分数描述器的示例,这里再展示一下:
1 | class score_desc(object): |
这里有一个严重的问题,就是stu_scores的math_score或者chinese_score都是类属性,这样导致如果有多个学生将无法记录。所以描述器还需要针对不同的实例给不同的存储,这时候一般使用字典,键值是实例。
修改如下:
1 | # coding=utf8 |
测试:
1 | stu1 = stu_scores() |
输出:
1 | 90 |
这里可以看到已经可以记录不同学生数据了。
实现缓存器
Flask使用的werkzeug中有用到描述器实现了一个缓存器。其在werkzeug.utils中。
1 | class _Missing(object): |
使用示例:
1 | class Foo(object): |
输出:
1 | foo test |
上面可以看出如果该函数被调用过,再次调用的时候会直接去dict中找,从而达到缓存的目的。
内置property描述器
内置的property是常用于修饰函数,从而使其可以和实例属性一样访问的。该部分在Objects/descrobject.c中PyProperty_Type函数里面实现。
用法
下面是使用示例:
1 | class Circle(object): |
输出:
1 | 1 |
这里可以看出有两种方式使用property:
1、通过property装饰函数,即可用将函数变成属性访问的方式应用。
2、通过调用property函数,设置某一属性的get和set函数,即可在调用该属性时调用函数。
原理
由于property是通过C实现的,这里给出一个python的等价版本。
1 | class Property(object): |
这里可以看到通过property修饰后访问的时候就会使得原有的函数名变成了一个property的实例,是一个描述器,在访问的时候就会查找到调用其__get__函数。