Pythonの管理属性

8954 ワード

いくつかの内容を勉強します.
  • __getattr__および_setattr__メソッドは、未定義のプロパティ取得とすべてのプロパティ付与値を汎用プロセッサメソッド
  • に向ける.
  • __getattribute__メソッドは、すべての属性をPython 3に向ける.0クラスの1つの汎用プロセッサの方法
  • propertyは関数を内蔵し、特定の属性アクセスをgetとset処理関数に位置決めし、特性(Property)
  • とも呼ばれる.
  • 記述子プロトコルは、特定の属性アクセスを任意のgetおよびsetプロセッサメソッドを有するクラスのインスタンス
  • に位置決めする.
    プロパティ・プロトコルを使用すると、特定のプロパティのgetおよびset操作を、プロパティ・アクセス時にコードを自動的に実行できるように、提供された関数またはメソッドに指定できます.
    *基礎知識
    attribute=property(fget,fset,fdel,doc)の4つのパラメータは、属性attributeのget,set,delメソッド、ドキュメント情報をそれぞれ表します.
    #-*-coding:UTF-8-*-
    class Person:
        def __init__(self,name):
            self._name = name
        def getName(self):
            print('fetch...')
            return self._name
        def setName(self,value):
            self._name = value
            print('change...')
        def delName(self):
            print('remove...')
            del self._name
        name = property(getName,setName,delName,'name property docs')  #  name   property                name  
    if __name__ == '__main__':
        bob = Person('Bob Smith')
        print(bob.name)     #  getName     name  
        bob.name = 'Robert Smth'  #  setName     
        print(bob.name)
        del bob.name
        print(Person.name.__doc__)
    ####
    fetch...
    Bob Smith
    change...
    fetch...
    Robert Smth
    remove...
    name property docs
    [Finished in 0.3s]
    

    すべてのクラスプロパティと同様に、インスタンスと下位のサブクラスはプロパティを継承します.
    class Coder(Person):
        pass
    if __name__ == '__main__':
        bob = Coder('Bob Smith')
        print(bob.name)
    ###
    fetch...
    Bob Smith
    Coder   Person   name  
    

    計算プロパティ
    class PropSquare:
        def __init__(self, start):
            self.value = start
        def getX(self):
            return self.value**2
        def setX(self,value):
            self.value = value
        X = property(getX,setX)
    if __name__ == '__main__':
        P = PropSquare(3)
        Q = PropSquare(32)
        print(P.X)
        P.X = 4
        print(P.X)
        print(Q.X)
    ###
    9
    16
    1024
                          
    

    装飾を使用してプロパティを記述する
    #-*-coding:UTF-8-*-
    """
    @decorator
    def func(args):...
    
       
    def func(args):...
    func = decorator(func)
    """
    class Person:
        def __init__(self, name):
            self._name = name
        @property
        def name(self):
            """name property docs"""
            print('fetch.....')
            return self._name
    
        @name.setter
        def name(self,value):
            print('change')
            self._name = value
        @name.deleter
        def name(self):
            print('remove...')
            del self._name
    if __name__ == '__main__':
        rose = Person('Rose Jhon')
        print(rose.name)
        rose.name = 'Roose Jhon'
        print(rose.name)
        del rose.name
    ###
    fetch.....
    Rose Jhon
    change
    fetch.....
    Roose Jhon
    remove...
                。  set del     
    

    ディスクリプタ
    記述子は、属性アクセスをブロックする代替方法を提供します.プロパティは記述子の一種であり、property内蔵関数は特定のタイプの記述子を作成する簡略化された方法である.ディスクリプタプロトコルを使用すると、プロパティに特定のプロパティのgetおよびset操作を、プロパティにアクセスするときに自動的に実行されるコードを挿入する方法を提供し、プロパティの削除をブロックし、プロパティにドキュメントを提供することができます.記述子は独立したクラスとして作成され、メソッド関数のようにクラス属性に割り当てられます.また、サブクラスとインスタンスで*の基礎知識を継承することもできます.
    class Descriptor:
        def __get__(self,instance,owner):...
        def __set__(self,instance,value):...
        def __delete__(self,instance):.....
    

    これらのメソッドを持つクラスは記述子と見なすことができ、あるインスタンスが別のクラスのプロパティに割り当てられた場合、これらのメソッドは特殊です.プロパティにアクセスすると自動的に呼び出されます.記述子パラメータ:記述子クラスインスタンス(self)と記述子インスタンスに追加されたクライアントクラスのインスタンス(instance)が渡されます.get__アクセスメソッドはまた、記述子インスタンスが追加するクラスを指定するownerパラメータを追加的に受信します.
    #-*-coding:UTF-8-*-
    """
       
    """
    class Name:
        def __get__(self,instance,owner):
            print(self,instance,owner)
            return instance._name
        def __set__(self,instance,value):
            print('change')
            instance._name = value
        def __delete__(self,instance):
            print('remove')
            del instance._name
    """
            
    """
    class Person:
        def __init__(self,name):
            self._name = name
        name = Name()
    """
    self Name    
    instance Person    
    owner Person 
    """
    if __name__ == '__main__':
        bob = Person('Jim Green')
        print(bob.name)
        bob.name = 'Jam Green'
        del bob.name
    ###
    <__main__.name object="" at=""> <__main__.person object="" at=""> 
    Jim Green
    change
    remove
    

    記述子の計算プロパティ
        
    
    class DescSquare:
        def __init__(self,start):
            self.value = start
        def __get__(self,instance,owner):
            return self.value**2
        def __set__(self,instance,value):
            self.value = value
    class Client1:
        X = DescSquare(3) #                         
    if __name__ == '__main__':
        c1 = Client1()
        print(c1.X)
        print(Client1.X)
    

    ディスクリプタでのステータス情報の使用
  • ディスクリプタ状態ディスクリプタ動作のための内部データを管理するための
  • .
  • インスタンスのステータスには、クライアントクラスに関する情報と、クライアントクラスが作成する可能性のある情報
  • が記録されている.
    """
           
    """
    class DescState:
        def __init__(self,value):
            self.value = value
        def __get__(self,instance,owner):
            print('DescState get')
            return self.value*10
        def __set__(self,instance,value):
            print('DescState set')
            self.value = value
    class CalcAttrs:
        X = DescState(2)
        Y = 3
        def __init__(self):
            self.Z = 4
    if __name__ == '__main__':
        obj = CalcAttrs()
        print(obj.X,obj.Y,obj.Z)
    ####
    value         , CalcAttrs   value     
    

    記述子クラスの属性ではなく、顧客クラスに添付されたインスタンスを格納または使用する属性です.
    class InsState:
        def __get__(self,instance,owner):
            print('InsState get')
            return instance._Y*100
        def __set__(self,instance,value):
            print('InsState set')
            instance._Y = value
    class CalcAttrs1:
        X = DescState(2)
        Y = InsState()
        def __init__(self):
            self._Y = 3
            self.Z = 4
    if __name__ == '__main__':
        obj = CalcAttrs1()
        print(obj.X,obj.Y,obj.Z)
    ###
    DescState get
    InsState get
    20 300 4
              CalcAttrs1      (instance)
          instance._Y     obj   。 obj.Y        InsState  Y  __get__           
    

    __getattr__および_getattribute__
  • __getattr__定義されていない属性に対して実行する--つまり、属性はインスタンスに格納されていないか、親の1つから
  • を継承していない.
  • __getattribute__各属性については、属性アクセスをスーパークラスに渡すことによって再帰ループ
  • が発生しないように注意する必要がある.
    def __getattr__(self,name): #On undefined attribute fetch [obj.name]
    def __getattribute__(self,name):#on all attribute fetch [obj.name]
    def __setattr__(self,name,value):#on all attribute assignment [obj.name=value]
    def __delattr__(self,name): #on all attribute deletion [del obj.name]
      self         ,name            ,value          
    

    #-*-coding:UTF-8-*-
    class Catcher:
        def __getattr__(self,name):
            print('Get:',name)
        def __setattr__(self,name,value):
            print('Set:',name,value)
        def test(slef):
            print('test')
    class Wrapper:
        def __init__(self,obj):
            self.wrapper = obj
        def __getattr__(self,attrname):
            print('Trace:',attrname)
            return getattr(self.wrapper,attrname)
    if __name__ == '__main__':
        X = Catcher()
        X.job
        X.pay = 99
        Y = Wrapper(X)
        Y.test()
    ###
    Get: job
    Set: pay 99
    Trace: test
    test
    ####
    Catcher   X   X.job ,   getattr     (         )
    

    注意使用_setattr__および_getattribute__ループを避けるには
    #-*-coding:UTF-8-*-
    class Person:
        def __init__(self,name):
            self._name = name
        # def __getattr__(self,attr):
        #   if attr == 'name':
        #       print('fetch....')
        #       return self._name
        #   else:
        #       raise AttributeError(attr)
        def __getattribute__(self,attr):
            if attr == 'name':
                print('fetch')
                attr = '_name'
            return object.__getattribute__(self,attr)
        def __setattr__(self,attr,value):
            if attr=='name':
                print('change...')
                attr = '_name'
            print(attr)
            self.__dict__[attr] = value   #         self._name = value       
        def __delattr__(self,attr):
            if attr == 'name':
                print('remove...')
                attr = '_name'
            del self.__dict__[attr]
    if __name__ == '__main__':
        bob = Person('Bob Smith')
        print(bob.name)
        bob.name = 'Robert Smith'
        print(bob.name)
        del bob.name
        print('-'*20)
        sue = Person('Sue Jones')
        print(sue.name)
    -       self._name = name   __setattr__
    

    __getattr__および_getattribute__比較
  • __getattr__定義されていない属性をブロックし、定義された属性は
  • をブロックしません.
  • __getattribute__すべての属性取得をブロックし、管理されていない属性アクセスをスーパークラス取得器に指し示す必要があり、ループ
  • を回避する.