描述符

描述符的本質就是新式類,其至少實現了__get__(),__set__(),__delete__()中的一個,也被稱爲描述符協議;

__get__():在調用一個屬性時,觸發

__set__():在爲一個屬性賦值時,觸發

__delete__():在用del刪除屬性時,觸發

描述符的作用:用來代理另一個類的類屬性(必須是類屬性,不能在類的函數構造中),且描述符在自身調用,賦值,刪除屬性時不會被觸發

class Str:
    def __get__(self, instance, owner):
        print('觸發Strget',instance,owner)
    def __set__(self, instance, value):
        print('觸發Strset',instance,value)
    def __delete__(self, instance):
        print('觸發Strdel')
class Int:
    def __get__(self, instance, owner):
        print('觸發Intget',instance,owner)
    def __set__(self, instance, value):
        print('觸發Intset',instance,value)
    def __delete__(self, instance):
        print('觸發Intdel')
class People:
    name=Str()
    age=Int()
    def __init__(self,name,age):
        self.name=name
        self.age=age

#自身的實例不會觸發
s=Str()
s.x=1
del s.x
i=Int()
i.y=2
del i.y

#實例化people時觸發
p=People('alex',18)

#描述符Str的使用
p.name
p.name='Bart'
del p.name

#描述符Int的使用
p.age
p.age=19
del p.age

print(p.__dict__)#爲空,因爲name和age屬性被Str和Int代理,在Str和Int中處理,並沒有寫入p.__dict__中
print(People.__dict__)

描述符分兩種一 數據描述符:

1.數據描述符:至少實現了__get__()和__set__()

2. 非數據描述符:沒有實現__set__()

注意:

一 描述符本身應該定義成新式類,被代理的類也應該是新式類
二 必須把描述符定義成這個類的類屬性,不能爲定義到構造函數中
三 要嚴格遵循該優先級,優先級由高到底分別是
1.類屬性
2.數據描述符
3.實例屬性
4.非數據描述符
5.找不到的屬性觸發__getattr__()

class Str:
    def __get__(self, instance, owner):
        print('觸發Strget',instance,owner)
    def __set__(self, instance, value):
        print('觸發Strset',instance,value)
    def __delete__(self, instance):
        print('觸發Strdel')
class People:
    name=Str()
    def __init__(self,name):
        self.name=name

#類屬性>數據描述符>實例屬性
#數據符大於實例屬性
p=People('Alex')#觸發了__set__
p.name           #觸發了__get__
p.name='Bart'   #觸發了__set__
del p.name       #觸發了__delete__
print(p.__dict__)

#類屬性大於數據描述符
print('====>',People.__dict__['name'])
People.name='Bart'#不會觸發__set__,直接People.__dict__中name對應的值由__set__的內存地址改爲Bart
print('====>',People.__dict__['name'])
print(p.name)             #不再觸發__get__
class Str:
    def __get__(self, instance, owner):
        print('觸發Strget',instance,owner)
    # def __set__(self, instance, value):
    #     print('觸發Strset',instance,value)
    # def __delete__(self, instance):
    #     print('觸發Strdel')
class People:
    name=Str()
    def __init__(self,name):
        self.name=name

#實例大於非數據描述符
p=People('Alex')
p.name
p.name='Bart'
#都不會觸發

描述符的作用

描述符可以規定輸入的值的類型

class Type:
    def __init__(self,key,type):
        self.key=key
        self.type=type
    def __get__(self, instance, owner):
        print('觸發get')
        return instance.__dict__[self.key]
    def __set__(self, instance, value):
        print('觸發set')
        if not isinstance(value,self.type):
            raise TypeError('%s不是%s'%(value,self.type))
        else:
            instance.__dict__[self.key]=value
    def __delete__(self, instance):
        print('觸發del')
class People:
    name=Type('name',str)
    age=Type('age',int)
    salary=Type('salary',float)
    def __init__(self,name,age,salary):
        self.name=name
        self.age=age
        self.salary=salary
p1=People("alex",18,3000.0)
print(p1.__dict__)
p2=People('bart','18',3000)


發佈了51 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章