zoukankan      html  css  js  c++  java
  • python之属性描述符与属性查找规则

    描述符
    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__方法,就会报错

  • 相关阅读:
    echarts官网上的动态加载数据bug被我解决。咳咳/。
    jquery中的jsonp和js中的jsonp还有配合php实现的jsonp。
    jquery中的done和always解决ajax问题
    vue2.0使用watch监听对象属性
    gulp配合vue压缩代码格式化
    支持flv的播放神器
    前端组件化-Web Components【转】
    自定义异步加载资源插件
    【leetcode刷题笔记】Two Sum
    【leetcode刷题笔记】Longest Common Prefix
  • 原文地址:https://www.cnblogs.com/raind/p/10146160.html
Copyright © 2011-2022 走看看