• Python属性以及属性符简介


    属性描述符和属性查找过程

    属性描述符是一个类,只需实现下面方法中的一种该类就可以被称之为属性描述符

    1 class Person:
    2     def __get__(self, instance, owner):
    3         pass
    4         
    5     def __set__(self, instance, value):
    6         pass
    7         
    8     def __delete__(self, instance):
    9         pass

    只需实现上面三个魔法函数的一种就可以称该类为属性描述符

    property类实现了完整的描述符协议,通常可以只实现部分协议,

    描述符的作用是:创建一个实例,作为另一个类的类属性

      在下面的代码实例中,IntField是一个属性描述符,因为它都实现了这三种魔法方法,然后定义一个User类,里面的类变量是IntField属性描述符对象,当定义u.a = 30时,会调用__set__方法,从下面的图片中可以看到,self就是属性描述符对象,instance是User对象,value就是所附的值,这个有一种应用:就是判断输入的属性值是不是满足要求,可以用属性描述符来判断,在__set__函数里面加上判断,

     1 class IntField:
     2     def __get__(self, instance, owner):
     3         pass
     4 
     5     def __set__(self, instance, value):
     6         pass
     7 
     8     def __delete__(self, instance):
     9         pass
    10 
    11 
    12 class User:
    13     a = IntField()
    14 
    15 
    16 if __name__ == "__main__":
    17     u = User()
    18     u.a = 30

     下面的例子就是用__set__做判断用户的输入

     1 import numbers
     2 
     3 
     4 class IntField:
     5     def __get__(self, instance, owner):
     6         pass
     7 
     8     def __set__(self, instance, value):
     9         if not isinstance(value, numbers.Integral):
    10             raise ValueError("Int value need")
    11         else:
    12             self.value = value
    13 
    14     def __delete__(self, instance):
    15         pass
    16 
    17 
    18 class User:
    19     a = IntField()
    20 
    21 
    22 if __name__ == "__main__":
    23     u = User()
    24     u.a = "abc"

    从上面代码可以看出,现在赋值u.a = "abc",输出如下,可以看到功能成功实现。

     1 import numbers
     2 
     3 
     4 class IntField:
     5     def __get__(self, instance, owner):
     6         return 40
     7 
     8     def __set__(self, instance, value):
     9         if not isinstance(value, numbers.Integral):
    10             raise ValueError("Int value need")
    11         else:
    12             self.value = value
    13 
    14     def __delete__(self, instance):
    15         pass
    16 
    17 
    18 class User:
    19     a = IntField()
    20 
    21 
    22 if __name__ == "__main__":
    23     u = User()
    24     u.a = 30
    25     print(u.a)

    当想要获取对象的属性(属性描述符对象)的值时,它会调用__get__方法,如上所示,__get__方法返回的是40,当获取u.a的值时,会调用__get__方法返回40

    数据属性描述符:实现__get__和__set__方法

    非数据属性描述符:只实现__get__方法

     如果user是User类的实例,那么user.age(以及等价的getattr(user, 'age'))

    首先调用__getattribute__,如果类定义了__getattr__方法,那么在__getattribute__抛出AttributeError的时候就会调用__getattr__,而对于描述符(__get__)的调用,则是发生在__getattribute__内部的。

    user = User(), 那么user.age顺序如下:

    (1) 如果"age"是出现在User或其基类的__dict__中,且age是data descriptor(数据属性描述符), 那么调用其__get__方法,

    (2) 如果"age"出现在user(obj)对象的__dict__中,那么直接返回obj.__dict__['age'],否则

    (3)如果"age"出现在User或其基类__dict__中

    (3.1) 如果age是non-data descriptor(非数据属性描述符),那么调用其__get__方法,否则

    (3.2)返回__dict__['age']

    (4) 如果User有__getattr__方法,调用__getattr__方法,否则

    (5)抛出AttributeError

  • 相关阅读:
    JSON对象和字符串之间的相互转换
    Loadrunner 运行场景时:missing newline in XXX.dat 错误解决
    linux grep详解
    Object 保存到文件中
    'libxml/tree.h' file not found
    具有相同值的不同字符串常量在内存中是分开存储的
    为右键添加快速进入CMD的选项,Win7更简单
    iOS KVO & KVC
    南阳数乌龟——递归超时
    LibSVM笔记系列(3)——初学移植libsvm的C/C++版本
  • 原文地址:https://www.cnblogs.com/xiebinbbb/p/13722970.html
Copyright © 2020-2023  润新知