美文网首页
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 属性描述符合属性查找过程

    user.age=10 就是调用了age的IntField实例中的set方法输出 user.age:1 age 出...

  • Python 属性描述符和属性查找

    起因于 @property 装饰器,它可以将对函数的调用伪装成对属性的调用,就是不用加括号了。假设有这么一个类: ...

  • ★08.缓存属性和方法ID

    简介 在获取一个 属性/方法ID 的时候需要基于名称或者 属性/方法描述符 的 符号查找 , 符号查找 的代价相对...

  • 深入JavaScript Day10 - 【重点】原型链、认识O

    一、原型链、认识Object 1、对于下面代码,描述查找name的过程?(理解原型链是什么) obj找name属性...

  • swift8——属性

    属性分为计算属性和存储属性 计算属性:用来计算描述计算过程和就算结果的 存储属性:用来定义类和结构体的某些特征; ...

  • 属性查找

    python set get 解释: python descriptor 详解:正文descriptor简介 de...

  • 第15章 脚本化文档

    15.2 选取文档元素 按id属性查找:getElementById() 按name属性查找:getElement...

  • Python的属性搜索

    这是我总结的Python属性搜索的加长版,完整的描述了Python在做属性访问时的过程。了解Python属性搜索的...

  • 查找记录

    如何查找记录 通过属性查找(可能会有重复记录) 通过ID查找 通过属性查找的方法来查找记录 Mongo Queri...

  • 类属性和实例属性的查找顺序

    类属性:定义在类内部的变量和方法,统称为属性。 查找顺序 - MRO 查找 Python 的属性搜索算法,在 Py...

网友评论

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

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