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

  • 相关阅读:
    Linux基础(一)
    计算机基础之网络基础
    计算机基础之操作系统
    计算机基础之计算机硬件基础
    .NET Reflector 8.2支持VS2013高亮显示和代码地图视图
    jQuery图表开源软件
    8个实用的页面布局和用户界面jQuery插件
    关于mvc3.0RadioButtonFor的使用
    链式调用-python
    给实数用千分位方法输出结果
  • 原文地址:https://www.cnblogs.com/raind/p/10146160.html
Copyright © 2020-2023  润新知