Python-属性描述符

版权声明:转载请注明出处。 https://blog.csdn.net/paopaohll/article/details/83177744

属性描述符简介

描述符对象一般是作为其他类对象的属性而存在。在其内部定义了三个方法用来实现属性对象的查找、设置、删除行为。这三个方法分别是:

  1. get(self, instance, owner):定义当试图取出描述符的值时的行为。
  2. set(self, instance,value):定义当描述符的设定值或改变时的行为。
  3. delete(self, instance):定义当描述符的值被删除时的行为。
  • 只要实现__get__、set、__delete__方法中的一个就可以认为是描述符;
  • 只实现__get__方法的对象是非数据描述符,在初始化之后它们只能被读取;
  • 同时实现__get__和__set__的对象是数据描述符,这种属性是可读写的。

属性描述符查找过程

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

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()

那么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

猜你喜欢

转载自blog.csdn.net/paopaohll/article/details/83177744