Python 面向对象 描述器

概念

可以描述一个属性操作的对象

定义

定义方式1 property

class Person():
    def __init__(self):
        self.__age = 10
    
    def get_age(self):
        return self.__age
    
    def set_age(self, value):
        if value < 0:
            value = 0
        self.__age = value

    def del_age(self):
        del self.__age
    
    age = property(get_age, set_age, del_age)


p = Person()
# p.set_age(-10)
# print(p.get_age())

p.age = 19
print(p.age)
del p.age

19

定义方式2

class Age():
    def __get__(self, instance, owner):
        print('get')
    
    def __set__(self, instance, value):
        print('set')
    
    def __delete__(self, instance):
        print('delete')

class Person():
    age = Age()


p = Person()
p.age = 19
print(p.age)
del p.age

set
get
None
delete

调用细节

使用实例进行调用。
只在新式类有效,在经典类不生效。

方法拦截

  • 一个实例属性的正常访问顺序:
  • 实例对象自身的 __dict__ 字典
  • 对应类对象的 __dict__ 字典
  • 如果有父类,会再往上层的 __dict__ 字典中检测
  • 如果没找到,又定义了 __getattr__ 方法,就会调用这个方法

将描述器的__get__方法给嵌入到查找机制当中,就是通过__getattribute__ 来实现

调用优先级

资料描述器:实现了 get set
非资料描述器:仅实现了 get
优先级:资料描述器 > 实例属性 > 非资料描述器

class Age():
    def __get__(self, instance, owner):
        print('get')
    
    # def __set__(self, instance, value):
    #     print('set')
    
    # def __delete__(self, instance):
    #     print('delete')

class Person():
    age = Age()

    def __init__(self):
        self.age = 10


p = Person()
p.age = 19
print(p.age)

print(p.__dict__)

19
{‘age’: 19}

数据存储问题

class Age():
    def __get__(self, instance, owner):
        print('get')
        return instance.v
    
    def __set__(self, instance, value):
        print('set', self, instance, value)
        instance.v = value
    
    def __delete__(self, instance):
        print('delete')
        del instance.v

class Person():
    age = Age()


p = Person()
p.age = 19

p2 = Person()
p2.age = 11

print(p.age)
print(p2.age)

set <main.Age object at 0x03855990> <main.Person object at 0x04259850> 19
set <main.Age object at 0x03855990> <main.Person object at 0x04259DD0> 11
get
19
get
11

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章