pythonの記述子(_get_,_set_,_delete_)

6809 ワード

記述子(_get_,_set_,_delete_)
1記述子とは何か:記述子の本質は新しいクラスであり、この新しいクラスでは、少なくとも__が実現される.get__(),__set__(),__delete__()の1つであり、これは記述子プロトコル__とも呼ばれるget__():属性が呼び出されるとトリガーされます_set__():属性に値を割り当てると、トリガー_delete__():delで属性を削除するとトリガーされます
class Foo: # python3 Foo    ,        ,            
    def __get__(self, instance, owner):
        pass
    def __set__(self, instance, value):
        pass
    def __delete__(self, instance):
        pass

2記述子は何をしているのか:記述子の役割は別のクラスの属性をエージェントするために使用される(記述子をこのクラスのクラス属性として定義しなければならず、構造関数に定義できない)
class Foo:
    def __get__(self, instance, owner):
        print('  get')
    def __set__(self, instance, value):
        print('  set')
    def __delete__(self, instance):
        print('  delete')

#                ,                /  /  ,          
f1=Foo()
f1.name='egon'
f1.name
del f1.name
#   Str
#                       ,             
class Str:
    def __get__(self, instance, owner):
        print('Str  ')
        print(instance, owner)
    def __set__(self, instance, value):
        print('Str  ...')
        print(instance,value)
    def __delete__(self, instance):
        print('Str  ...')
        print(instance)


class People:
    name = Str()  # name      ,                  

    def __init__(self,name): #name Str   
        self.name = name

p1 = People('long')

#    Str   
p1.name
p1.name = 'sss'
del p1.name

print(p1.__dict__)
print(People.__dict__)

'''
  :
Str  ...
<__main__.people object="" at=""> long
Str  
<__main__.people object="" at=""> 
Str  ...
<__main__.people object="" at=""> sss
Str  ...
<__main__.people object="" at="">
{}
{'__module__': '__main__', 'name': <__main__.str object="" at="">, '__init__': , '__dict__': , '__weakref__': , '__doc__': None}


'''

3ディスクリプタは、少なくとも実装された2つのデータディスクリプタに分けられる.get__()と_set__()
class Foo:
    def __set__(self, instance, value):
        print('set')
    def __get__(self, instance, owner):
        print('get')

二非データ記述子:実装されていません_set__()
class Foo:
    def __get__(self, instance, owner):
        print('get')


4注意事項:記述子自体は新式クラスとして定義すべきであり、エージェントされるクラスも新式クラス2であるべきである.記述子をこのクラスのクラス属性として定義しなければならない.コンストラクション関数に定義された3つの優先度に厳密に従うことはできない.優先度は、それぞれ1>クラス2>データ記述子3>インスタンス属性4>非データ記述子5>見つからない属性によってトリガーされる.getattr__()
5記述子の使用
pythonは弱い言語であることはよく知られています.すなわち、パラメータの付与にはタイプ制限がありません.次に、記述子メカニズムによってタイプ制限機能を実現します.
#   
class Typed:
    def __init__(self,key):
        self.key = key

    def __get__(self, instance, owner):
        print('get  ')
        # print('instance  :%s'%instance) # People object
        # print('owner  :%s'%owner)
        return instance.__dict__[self.key]

    def __set__(self, instance, value):
        #      :               
        print('set  ')
        # print('instance  :%s'%instance) # People Object
        # print('value  :%s'%value)
        if not isinstance(value,str):
            raise TypeError('           ')
        instance.__dict__[self.key] = value

    def __delete__(self, instance):
        print('delete  ')
        # print('instance  :%s'%instance) # People object
        instance.__dict__.pop(self.key)

class People:
    name = Typed('name')  #    
    def __init__(self,name,age,salary):
        self.name = name
        self.age = age
        self.salary = salary

p1 = People('asd',18,330)  # (     >  )     ,  __set__
print(p1.__dict__)
print('-----------------')
p1.name = 'log'
print(p1.__dict__)
print('------------------')
name = p1.name
print(name)
print('------------------')
del p1.name
print(p1.__dict__)
'''
  :
set  
{'name': 'asd', 'age': 18, 'salary': 330}
-----------------
set  
{'name': 'log', 'age': 18, 'salary': 330}
------------------
get  
log
------------------
delete  
{'age': 18, 'salary': 330}
'''

# -------------     name       -----------------
p2 = People(321,18,330)
'''
Traceback (most recent call last):
set  
  File "F:/Python3/   /    /day4/     .py", line 60, in 
    p2 = People(321,18,330)
  File "F:/Python3/   /    /day4/     .py", line 29, in __init__
    self.name = name
  File "F:/Python3/   /    /day4/     .py", line 18, in __set__
    raise TypeError('           ')
TypeError:            
'''
#   
class Typed:
    def __init__(self,key,key_type):
        self.key = key
        self.key_type = key_type
    def __get__(self, instance, owner):
        print('get  ')
        # print('instance  :%s'%instance) # People object
        # print('owner  :%s'%owner)
        return instance.__dict__[self.key]

    def __set__(self, instance, value):
        #      :               
        print('set  ')
        # print('instance  :%s'%instance) # People Object
        # print('value  :%s'%value)
        if not isinstance(value,self.key_type):
            raise TypeError('%s  %s'%(value,self.key_type))

        instance.__dict__[self.key] = value

    def __delete__(self, instance):
        print('delete  ')
        # print('instance  :%s'%instance) # People object
        instance.__dict__.pop(self.key)

class People:
    name = Typed('name',str)  #    
    age = Typed('age',int)
    def __init__(self,name,age,salary):
        self.name = name
        self.age = age
        self.salary = salary


# ----------------------3        -------------------
p1 = People('long','18',2000)
'''
Traceback (most recent call last):
set  
  File "F:/Python3/   /    /day4/     .py", line 76, in 
set  
    p1 = People('long','18',2000)
  File "F:/Python3/   /    /day4/     .py", line 32, in __init__
    self.age = age
  File "F:/Python3/   /    /day4/     .py", line 18, in __set__
    raise TypeError('%s  %s'%(value,self.key_type))
TypeError: 18  
'''