python記述子一言解釈、概要とピット

5515 ワード

記述子は単一の属性を維持するためのクラスです
記述子の2つの部分:
1.記述子の説明
2.記述子の実用化
記述子は独立したクラスである.
特性(property、別の文章で紹介し説明した2つの方式)は記述子の1つである.
ディスクリプタは、プロパティのブロッキング(取得/変更(設定)/削除)に使用されます.
具体的には、ある特定の属性を取得/削除/設定の面でブロックすることで、
ユーザー自身に定義されるプロセス
記述子インスタンスはクラス属性を付与するために使用されることを覚えておいてください.以下で説明します.
簡単な記述子:
class Descriptor:
    def __get__(self, instance, owner):pass
    def __set__(self, instance, value):pass
    def __delete__(self, instance):pass

いずれかの3つの方法のうちの1つを記述子と見なすことができる.
__get__ : 取得,_set__ :設定/変更、_delete:削除[delete:さくじょ]
#   
#         ,  /   ,   
#    
#    __get__, __set__ , __delete__             
class D:      #     ,      __get__   
    def __get__(self, instance, owner):     #  :     ,          ,     
                                            #3         
        print(self,instance,owner,sep='\t')

class Sub:
    attr = D()      #       , Sub.attr ,          
s = Sub()
s.attr              #   attr .   attr       => D.__get__(Sub.attr, s, Sub)
Sub.attr
#echo:
#<__main__.d object="" at="">	<__main__.sub object="" at="">	
#<__main__.d object="" at="">	None	
#      ,  python     
s.attr = '123'         #    attr    ?    s         attr   
print(s.__dict__)

記述子に__が含まれている場合set__ メソッドの場合、インスタンスは通常のレベル割り当て動作を使用しません.
#       ,        :           __set__
class D:
    def __get__(self, instance, owner):
        print(D.__get__.__name__ , ' invoked')
    def __set__(self, instance, value):
        print(D.__set__.__name__, ' invoked' , ',value:' ,value)
        #raise AttributeError("    ")      attr      ,    set     
class C:
    attr = D()

c = C()
c.attr = 1      #       __set__      ,     : D.__set__(C.attr,c,C)
次の完全な実際の例
#     
#                ,  /  ,  
#    ,                .         ,      
class Name:
    "     "
    def __get__(self, instance, owner):             #  
        print(Name.__get__.__name__, ' invoked!')
        return instance._name
    def __set__(self, instance, value):             #  
        print(Name.__set__.__name__, ' invoked!')
        instance._name = value
    def __delete__(self, instance):
        print(Name.__delete__.__name__ , " invoked!") #    
        del instance._name

class Person:
    def __init__(self , name = "Person"):
        self._name = name
    name = Name()           #      name    ,           

p = Person()
print(p.name)               #   Name.__get__(Person.name,p , Person)
p.name = 'hi'              #   Name.__set__(Person.name,p,'hi')
del p.name                 #   Name.__delete__(Person.name,p)
#echo
#__get__  invoked!
#Person
#__set__  invoked!
#__delete__  invoked!
#                      ,            
class Person:
    def __init__(self,value = 'Person'):
        self._name = value
    #          ,     
    class DescriptorName:
        def __get__(self, instance, owner):
            print(self.__class__.__name__,' __get__')
            return instance._name
        def __set__(self, instance, value):
            print(self.__class__.__name__,'__set__')
            instance._name = value
        def __delete__(self, instance):
            print(self.__class__.__name__,'__delete__')
            del instance._name
    name = DescriptorName()         #         
p1 = Person()
p1.name

1つの属性を特殊化する場合、記述子を使用することを考慮することができ、この属性を使用する場合、実際に記述子オブジェクトを使用して処理される.
記述子クラスに__を追加する具体的な例を次に示します.init__ , 記述子も一般的なクラスであり、属性を追加することもできます.
#     
class DescState:
    #    init ,             value
    def __init__(self,value):
        self.value = value
    def __get__(self, instance, owner):
        print(DescState.__name__,DescState.__get__.__name__,'invoked!',sep='\t')
        return self.value
    def __set__(self, instance, value):
        print(DescState.__name__,DescState.__get__.__name__, ' invoked!',sep='\t')
        self.value = value

#     
#              _name
class InstState:
    def __get__(self, instance, owner):
        print(InstState.__name__,'__get__ invoked!')
        return instance._name               #        : _name
    def __set__(self, instance, value):
        print(InstState.__name__,'__set__ invoked!')
        instance._name = value
#     
#attr_desc         
#attr_inst          :_name   ,  
#      2   , _name, _instAttr
class ClientClass:
    attr_desc = DescState(10)       #         ,      ,             
    attr_inst = InstState()         #         ,                  :_name
    def __init__(self,name = 'ClientClass'):
        self._name = name           #2     
        self._instAttr = 1

obj = ClientClass()
#  3      ,    
#     : 1.DescState.__get__() 2.InstState.__get__()
print(obj.attr_desc ,obj.attr_inst,obj._instAttr)
#echo:
#DescState	__get__	invoked!
#InstState __get__ invoked!
#10 ClientClass 1

obj.attr_desc = 5           #DescState.__set__()
obj.attr_inst = 6           #InstState.__set__()
obj._instAttr = 7
print(obj.attr_desc ,obj.attr_inst,obj._instAttr)
#echo:
#DescState	__set__	 invoked!
#InstState __set__ invoked!
#DescState	__get__	invoked!
#InstState __get__ invoked!
#5 6 7