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

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