zoukankan      html  css  js  c++  java
  • 【7.3】属性描述符和属性查找过程

    属性描述符--利用的是抽象的方法, 把十几个字段共同的特性抽出来,每个字段都用这个特性,达到节省代码的目的。

    属性描述符,有数据属性描述符和非数据属性描述符

       __get__

       __set__

       __delete__

      实现上述三个魔法函数其中之一即可成为属性描述符,如果只实现__get__称之为非数据属性描述符,只有同时实现__get__和__set__才称之为数据属性描述符

     1 #!/user/bin/env python
     2 # -*- coding:utf-8 -*-
     3 import numbers
     4 
     5 
     6 class IntField:
     7     def __get__(self, instance, owner):
     8         return self.value
     9 
    10     def __set__(self, instance, value):
    11         if not isinstance(value, numbers.Integral):
    12             raise ValueError('int value need')
    13         if value < 0:
    14             raise ValueError('positive value need')
    15         self.value = value
    16 
    17     def __delete__(self, instance):
    18         pass
    19 
    20 
    21 class User:
    22     age = IntField()
    23 
    24 
    25 if __name__ == '__main__':
    26     user = User()
    27     user.age = 30
    28     print(user.age)
    29 
    30     # ValueError('int value need')
    31     # user.age = 'z'
    32     # print(user.age)
    33 
    34     # ValueError('positive value need')
    35     # user.age = -1
    36     # print(user.age)
    30
    

      总结一下:

        1.需要把校验放在一个类里面(IntField)

        2.需要重写魔法函数

        3.age = IntField()

        4.给age赋值的时候,会调用IntField里面的__get__方法

    属性查找过程

      如果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的__dict__中(对象属性), 那么直接返回 obj.__dict__['age'], 否则  -->如果age不是类属性或者User不是数据属性描述符,则去对象属性中查找age
    (3)如果“age”出现在User或其基类的__dict__中(类属性)
    (3.1)如果age是non-data descriptor,那么调用其__get__方法, 否则
    (3.2)返回 class.__dict__['age']
    (4)如果User有__getattr__方法,调用__getattr__方法,否则  -->对象属性和类属性中都没有age,则调用User类的__getattr__方法
    (5)抛出AttributeError

    (3.1)

     1 #!/user/bin/env python
     2 # -*- coding:utf-8 -*-
     3 import numbers
     4 
     5 
     6 class IntField:
     7     def __get__(self, instance, owner):
     8         return self.value
     9 
    10     def __set__(self, instance, value):
    11         if not isinstance(value, numbers.Integral):
    12             raise ValueError('int value need')
    13         if value < 0:
    14             raise ValueError('positive value need')
    15         self.value = value
    16 
    17     def __delete__(self, instance):
    18         pass
    19 
    20 
    21 class NotDataIntField:
    22     def __get__(self, instance, owner):
    23         return self.value
    24 
    25 
    26 class User:
    27     age = NotDataIntField()
    28 
    29 
    30 if __name__ == '__main__':
    31     user = User()
    32     User.age = 30
    33     User.z = 10
    34     print(User.__dict__)
    35     print(user.__dict__)
    36     print(User.age)
    37     print(user.age)
    38 
    39     # ValueError('int value need')
    40     # user.age = 'z'
    41     # print(user.age)
    42 
    43     # ValueError('positive value need')
    44     # user.age = -1
    45     # print(user.age)
    {'__module__': '__main__', 'age': 30, '__dict__': <attribute '__dict__' of 'User' objects>, '__weakref__': <attribute '__weakref__' of 'User' objects>, '__doc__': None, 'z': 10}
    {}
    30
    30
    

      

  • 相关阅读:
    P5304旅行者(比bk201还要流氓的解法)
    考试T1护花
    考试T2修剪草坪
    考试T3麻将
    账号密码
    T7
    P2885 [USACO07NOV]电话线Telephone Wire
    P4965 薇尔莉特的打字机
    P1505 [国家集训队]旅游
    T2
  • 原文地址:https://www.cnblogs.com/zydeboke/p/11265485.html
Copyright © 2011-2022 走看看