描述符 __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输入有误
'''

这就是描述符的应用!

猜你喜欢

转载自www.cnblogs.com/zach0812/p/11312252.html