美文网首页
8-3 属性描述符合属性查找过程

8-3 属性描述符合属性查找过程

作者: 正在努力ing | 来源:发表于2018-08-26 15:35 被阅读0次
    import numbers
    '''
    如果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’], 否则
    
    (3)如果“age”出现在User或其基类的__dict__中
    
    (3.1)如果age是non-data descriptor,那么调用其__get__方法, 否则
    
    (3.2)返回 __dict__[‘age’]
    
    (4)如果User有__getattr__方法,调用__getattr__方法,否则
    
    (5)抛出AttributeError
    
    '''
    class IntField:
        """数据描述符"""
        def __get__(self, instance, owner):
            return self.value
    
        def __set__(self, instance, value):
            if isinstance(value,numbers.Integral):
                self.value = value
            else:
                raise ValueError
    
        def __delete__(self, instance):
            pass
    
    class NotIntField:
        """非数据描述"""
        def __get__(self, instance, owner):
            return 31
    
    class User:
        age = IntField()
        # age = NotIntField()
    
        def __init__(self,name,weight):
            self.name = name
            self.weight = weight
    
    user = User("zhou",34)
    user.age = 10
    print(user.__dict__)
    print("User.__dict__:          ", User.__dict__)
    print("IntField.__dict__:      ", IntField.__dict__)
    print(user.age)
    
    {'name': 'zhou', 'weight': 34}
    User.__dict__:           {'__doc__': None, '__weakref__': <attribute '__weakref__' of 'User' objects>, '__module__': '__main__', 'age': <__main__.IntField object at 0x0000000004D11470>, '__init__': <function User.__init__ at 0x0000000004D7C268>, '__dict__': <attribute '__dict__' of 'User' objects>}
    IntField.__dict__:       {'__set__': <function IntField.__set__ at 0x0000000004D7C158>, '__get__': <function IntField.__get__ at 0x0000000004D7CD90>, '__doc__': '数据描述符', '__weakref__': <attribute '__weakref__' of 'IntField' objects>, '__module__': '__main__', '__delete__': <function IntField.__delete__ at 0x0000000004D7CE18>, '__dict__': <attribute '__dict__' of 'IntField' objects>}
    10
    

    user.age=10 就是调用了age的IntField实例中的set方法
    输出 user.age:
    1 age 出现在User的dict中,而且age是数据描述符,所以调用IntField实例的get方法

    class User:
        age = IntField()
        # age = NotIntField()
    
        def __init__(self,name,weight):
            self.name = name
            self.weight = weight
    
    
    user = User("zhou",34)
    user.__dict__["age"] = "ab"
    print(user.__dict__["age"])
    print("user.__dict__:          ", user.__dict__)
    print("User.__dict__:          ", User.__dict__)
    print("IntField.__dict__:      ", IntField.__dict__)
    print(user.age)
    
    
        ab
        user.__dict__:           {'name': 'zhou', 'age': 'ab', 'weight': 34}
        User.__dict__:           {'__doc__': None, '__weakref__': <attribute '__weakref__' of 'User' objects>, '__module__': '__main__', 'age': <__main__.IntField object at 0x0000000004D913C8>, '__init__': <function User.__init__ at 0x0000000004D7CF28>, '__dict__': <attribute '__dict__' of 'User' objects>}
        IntField.__dict__:       {'__set__': <function IntField.__set__ at 0x0000000004D7C158>, '__get__': <function IntField.__get__ at 0x0000000004D7CD90>, '__doc__': '数据描述符', '__weakref__': <attribute '__weakref__' of 'IntField' objects>, '__module__': '__main__', '__delete__': <function IntField.__delete__ at 0x0000000004D7CE18>, '__dict__': <attribute '__dict__' of 'IntField' objects>}
        
    
    
        ---------------------------------------------------------------------------
    
        AttributeError                            Traceback (most recent call last)
    
        <ipython-input-12-621de20b36d7> in <module>()
             14 print("User.__dict__:          ", User.__dict__)
             15 print("IntField.__dict__:      ", IntField.__dict__)
        ---> 16 print(user.age)
        
    
        <ipython-input-11-efe384b96662> in __get__(self, instance, owner)
             25     """数据描述符"""
             26     def __get__(self, instance, owner):
        ---> 27         return self.value
             28 
             29     def __set__(self, instance, value):
        
    
        AttributeError: 'IntField' object has no attribute 'value'
    

    user.dict["age"] = "ab",没有调用set方法,所以不会存在self.value
    输出 user.age:
    1 age 出现在User的dict中,而且age是数据描述符,所以调用IntField实例的get方法 ,因为没有执行 set方法,所以不会存在self.value;报错

    class User:
        # age = IntField()
        age = NotIntField()
    
        def __init__(self,name,weight):
            self.name = name
            self.weight = weight
    
    user = User("zhou",34)
    user.age = 10
    print(user.__dict__)
    print(IntField.__dict__)
    print(user.age)
    
    
        {'name': 'zhou', 'age': 10, 'weight': 34}
        {'__set__': <function IntField.__set__ at 0x0000000004D7C158>, '__get__': <function IntField.__get__ at 0x0000000004D7CD90>, '__doc__': '数据描述符', '__weakref__': <attribute '__weakref__' of 'IntField' objects>, '__module__': '__main__', '__delete__': <function IntField.__delete__ at 0x0000000004D7CE18>, '__dict__': <attribute '__dict__' of 'IntField' objects>}
        10
    

    输出 user.age:
    1 age 出现在User的dict中,但是age不是数据描述符,所以往下找;
    2 “age”出现在user的dict中, 那么直接返回 obj.dict[‘age’],

    相关文章

      网友评论

          本文标题:8-3 属性描述符合属性查找过程

          本文链接:https://www.haomeiwen.com/subject/sneoiftx.html