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

    from datetime import date, datetime
    import numbers
    
    
    class IntField:
        # 数据描述符
        def __get__(self, instance, owner):
            return self.value
    
        def __set__(self, instance, value):
            if not isinstance(value, numbers.Integral):
                raise ValueError("int value need")
            if value < 0:
                raise ValueError("positive value need")
            self.value = value
    
        def __delete__(self, instance):
            pass
    
    
    class NonDataIntField:
        # 非数据属性描述符
        def __get__(self, instance, owner):
            return self.value
    
    
    class User:
        age = IntField()
        # age = NonDataIntField()
    
    
    '''
    如果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 User:
    #
    #     def __init__(self, name, email, birthday):
    #         self.name = name
    #         self.email = email
    #         self.birthday = birthday
    #         self._age = 0
    #
    #     # def get_age(self):
    #     #     return datetime.now().year - self.birthday.year
    #
    #     @property
    #     def age(self):
    #         return datetime.now().year - self.birthday.year
    #
    #     @age.setter
    #     def age(self, value):
    #         #检查是否是字符串类型
    #         self._age = value
    
    if __name__ == "__main__":
        user = User()
        user.__dict__["age"] = "abc"
        print(user.__dict__)
        print(user.age)
        # print (getattr(user, 'age'))
        # user = User("bobby", date(year=1987, month=1, day=1))
        # user.age = 30
        # print (user._age)
        # print(user.age)

    只要是类中实现任一个__get__,__set__ ,__delete__方法中的任意一个方法,他都是属性描述符的对象,

    通过属性描述符就可以控制赋值的属性。

    数据属性描述符和非数据属性描述符的区别:

    1,数据属性描述符实现三个方法,但是非数据属性描述符仅实现__get__

    2,在类中且属于属性描述符,优先调用

  • 相关阅读:
    完全背包
    二分求值(二分适合求答案在两个数之间的题目)
    set<pair<int,int> >的用法
    01背包 (dp专题)
    矩阵快速幂
    BZOJ1977 [BeiJing2010组队]次小生成树 Tree
    BZOJ1854 [Scoi2010]游戏
    BZOJ1054 [HAOI2008]移动玩具
    NOIP系列复习及题目集合
    BZOJ2708 [Violet 1]木偶
  • 原文地址:https://www.cnblogs.com/zhoulixiansen/p/10061014.html
Copyright © 2011-2022 走看看