描述符
import numbers
class IntgerField:
def __get__(self, isinstance, owner):
print('获取age')
return self.num def __set__(self, instance, value):
print('设置age值时')
if not isinstance(value, numbers.Integral):
raise ValueError('int need')
self.num = value
def __delete__(self, instance):
pass class User:
age = IntgerField() // 数据属性描述符,查找优先级最高 user = User()
user.age = 33
print(user.age)



上述的User可以看做数据库中的表,假设我们要控制user中age的赋值类型,固然可以使用以下形式进行拦截:

class User:
age = 33
def __setattr__(self, name, value):
pass // 这里进行类型检测
又或者:
class User:
@property
def age(self):
return self._num
@age.setter
def age(self,value):
self._num = value // 这里进行类型检测

但是这种一两次还行,多了就是在写重复代码,所以就可用上述类IntgerField中定义__get__,__set__等实现属性描述符的方式进行拦截。

getattributegetattrsetattr、__delattr__等方法用来实现属性查找、设置、删除的一般逻辑,而对属性的控制行为就由属性对象来控制。这里单独抽离出来一个属性对象,在属性对象中定义这个属性的查找、设置、删除行为。这个属性对象就是描述符。

描述符对象一般是作为其他类对象的属性而存在。在其内部定义了三个方法用来实现属性对象的查找、设置、删除行为。这三个方法分别是:

get(self, instance, owner):定义当试图取出描述符的值时的行为。

set(self, instance, value):定义当描述符的值改变时的行为。

delete(self, instance):定义当描述符的值被删除时的行为。

其中:instance为把描述符对象作为属性的对象实例;

owner为instance的类对象。

描述符有数据描述符和非数据描述符之分

只要至少实现__get__、set、__delete__方法中的一个就可以认为是描述符;

只实现__get__方法的对象是非数据描述符,意味着在初始化之后它们只能被读取;

同时实现__get__和__set__的对象是数据描述符,意味着这种属性是可读写的。

属性查找规则

当查找对象上的某个属性时,假设是user.age,顺序先是判断该实例所指向的类以及基类的__dict__中查找,并且如果该属性数据属性描述符,就会调用描述符中的__get__方法

如果该age直接出现在obj.__dict__上,直接返回obj.dict['age']

如果该属性出现在User中或基类中,且该属性是非数据属性描述符,就会调用其__get__方法,如果不是非数据属性描述符,就会调用User或基类的User或基类.dict['age']

如果这些都没有,且User上也没有__getattr__方法,就会报错

最新文章

  1. 手工给Meteor增加smart package的方法
  2. JavaScript事件对象与事件处理程序
  3. Jetty 服务器的知识
  4. Flash Air 打包安卓 ane
  5. 【英语】Bingo口语笔记(19) - 如何用英语叙旧
  6. 抽象类[abstract]_C#
  7. Class.forName()的作用与使用总结(转载)
  8. SQL Server 手把手教你使用profile进行性能监控
  9. 图片验证码demo示例
  10. 浅析跨域的方法之一 JSONP
  11. mapreduce shuffle 和sort 详解
  12. python 上台阶
  13. OpenCV入门之获取验证码的单个字符(二)
  14. 用ABP只要加人即可马上加快项目进展(二) - 分工篇
  15. msql 复杂练习
  16. 最最最最最基础的SQL Server
  17. InnoDB Next-Key Lock
  18. jquery mobile两个页面以及源码(登录与注册) 转
  19. 《react精髓》读书笔记
  20. SSH三大框架需要的jar包

热门文章

  1. C++ 函数的重载和参数默认值
  2. 谈谈jQuery中的数据类型检测
  3. 人人开源分模块,非原生html报错,很难查找问题所在,有vue语法
  4. Applet、Scriptlet与Servlet
  5. 【编程拾遗】C++的static成员函数与单例模式
  6. 【转载】双调排序Bitonic Sort,适合并行计算的排序算法
  7. 阿里云上 配置 vsftpd 配置文件 (一个成功例子)
  8. CF1091F New Year and the Mallard Expedition
  9. 【ARTS】01_14_左耳听风-20190211~20190217
  10. 【转】python编写规范——中标软件有限公司测试中心