zoukankan      html  css  js  c++  java
  • 描述符 __set__(),__get__(),__delete__()

     1 class Str:
     2     def __set__(self, instance, value):
     3         print("Str_set",instance,value)
     4         print(id(instance)) #instance 是 Person() 的实例对象 
     5 
     6 
     7     def __get__(self, instance, owner):
     8         print("Str_get")
     9 
    10     def __delete__(self, instance):
    11         print("Str_delete")
    12 
    13 class Person:
    14     name = Str()
    15     def __init__(self,name):
    16         self.name = name
    17 
    18 if __name__ == "__main__":
    19     p = Person("tom")
    20     print(id(p))
    21 '''
    22     Str_set <__main__.Person object at 0x00000194CA51B0F0> tom
    23     1738561138928
    24     1738561138928
    25 '''

    优先级:类属性> 数据描述符(必有set)>实例属性>非数据描述符(只有get)>找不到

    类属性>数据>实例
    1 class Str: 2 def __set__(self, instance, value): 3 print("Str_set") 4 5 def __get__(self, instance, owner): 6 print("Str_get") 7 8 def __delete__(self, instance): 9 print("Str_delete") 10 11 class Person: 12 name = Str() 13 def __init__(self,name): 14 self.name = name 15 16 if __name__ == "__main__": #有set 和delete 的是数据描述符 反之是非数据(只有get) 17 p = Person("tom") #因为实例小于数据描述符 数据描述符起作用 18 #Person.name = "tom" # 类属性的优先级高于数据描述符 数据描述符不起作用 19 #del Person.name #类属性优先级高于数据描述符 数据描述符不起作用 20 # Person.name #类属性字典中没有 数据描述符起作用 21 22 p.name = "tom" #实例小于数据描述符 数据描述符起作用 23 del p.name #实例小于数据描述符 数据描述符起作用 24 p.name #实例小于数据描述符 数据描述符起作用

     实例>非数据>找不到

    1 class Str: 2 # def __set__(self, instance, value): 3 # print("Str_set") 4 5 def __get__(self, instance, owner): 6 print("Str_get") 7 # 8 # def __delete__(self, instance): 9 # print("Str_delete") 10 11 class Person: 12 name = Str() 13 def __init__(self,name): 14 self.name = name 15 16 if __name__ == "__main__": 17 p = Person("tom") #因为实例大于非数据描述符 数据描述符不起作用 18 19 p.name = "jack" #因为实例大于非数据描述符 数据描述符不起作用 20 p.name #因为实例大于非数据描述符 数据描述符不起作用 21 del p.name #因为实例大于非数据描述符 数据描述符不起作用 22 #================================ 23 24 p.name #此时非数据描述符大于找不到,就起作用了 25 ''' 26 输出: 27 28 Str_get 29 '''

    描述符的应用:

    众所周知,Python是弱类型的语言,即参数的赋值没有类型的限制,下面通过描述符的机制实现类型限制功能。

    1 class Person:
    2     def __init__(self,name,age,salary):
    3         self.name = name
    4         self.age = age
    5         self.salary = salary
    6 
    7 if __name__ =="__main__":
    8     p1 = Person("tom",18,100)
    9     p2 = Person(108,"tom","jack")  #程序是不会报错的,需求就是让它做类型检测
     1 class Check:
     2     def __init__(self,key):
     3         self.key = key
     4 
     5     def __set__(self, instance, value):
     6         print("set")
     7         if isinstance(value,str):
     8             instance.__dict__[self.key] = value
     9         else:
    10             print("{}输入有误".format(self.key))
    11     def __get__(self, instance, owner):
    12         print("get")
    13         return instance.__dict__[self.key]
    14 
    15     def __delete__(self, instance):
    16         print("delete")
    17         instance.__dict__.pop(self.key)
    18 
    19 class Person:
    20     name = Check("name") #传入“name” 方便操作Person实例对象的属性字典
    21     def __init__(self,name,age,salary):
    22         self.name = name
    23         self.age = age
    24         self.salary = salary
    25 
    26 if __name__ =="__main__":
    27     p1 = Person("tom",18,100)
    28     p2 = Person(108,"tom","jack")
    29 '''
    30     输出:  
    31     set
    32     set
    33     name输入有误
    34 '''

    改进一:

     1 class Check:
     2     def __init__(self,key):
     3         self.key = key
     4 
     5     def __set__(self, instance, value):
     6         print("set")
     7         if isinstance(value,str):
     8             instance.__dict__[self.key] = value
     9         else:
    10             raise TypeError("{}输入有误".format(self.key))  #这样如果有误直接就将程序停止了
    11             # print("{}输入有误".format(self.key))
    12     def __get__(self, instance, owner):
    13         print("get")
    14         return instance.__dict__[self.key]
    15 
    16     def __delete__(self, instance):
    17         print("delete")
    18         instance.__dict__.pop(self.key)
    19 
    20 class Person:
    21     name = Check("name") #传入“name” 方便操作Person实例对象的属性字典
    22     def __init__(self,name,age,salary):
    23         self.name = name
    24         self.age = age
    25         self.salary = salary
    26 
    27 if __name__ =="__main__":
    28     p1 = Person("tom",18,100)
    29     p2 = Person(108,"tom","jack")

     终极版:

    class Check:
        def __init__(self,key,type):
            self.key = key
            self.type= type
    
        def __set__(self, instance, value):
            print("set")
            if isinstance(value,self.type):
                instance.__dict__[self.key] = value
            else:
                print("{}输入有误".format(self.key))
                # raise TypeError("{}输入有误".format(self.key))
        def __get__(self, instance, owner):
            print("get")
            return instance.__dict__[self.key]
    
        def __delete__(self, instance):
            print("delete")
            instance.__dict__.pop(self.key)
    
    class Person:
        name = Check("name",str)
        age = Check("age",int)
        salary = Check("salary",float)
        def __init__(self,name,age,salary):
            self.name = name
            self.age = age
            self.salary = salary
    
    if __name__ =="__main__":
        p1 = Person("tom",18,100.0)
        print("============")
        p2 = Person(108,"tom","jack")
    
    '''
    set
    set
    set
    ============
    set
    name输入有误
    set
    age输入有误
    set
    salary输入有误
    '''

    这就是描述符的应用!

  • 相关阅读:
    jichu
    scanf
    数位dp
    hdu 5667
    华东交通大学2018年ACM“双基”程序设计竞赛 K
    华东交通大学2018年ACM“双基”程序设计竞赛 D
    map
    次小生成树
    set
    c++11之为什么C++11引入了std::ref?
  • 原文地址:https://www.cnblogs.com/zach0812/p/11312252.html
Copyright © 2011-2022 走看看