python:一段代码看懂Descriptor

先看代码和执行结果,很简单:

python:一段代码看懂Descriptor_第1张图片
image.png

然后去掉第18行的注释:


python:一段代码看懂Descriptor_第2张图片
image.png

和之前唯一的区别是第25行的输出。
想一想:为什么第21行定义的self.p没有覆盖第18行定义的类属性p?

因为这里的类属性p是Descriptor(这里为class P)的实例
来看看完整的代码:

#!/usr/bin/env python3                  
                                        
class P:                                
    def __init__(self, v):              
        self.data = v                   
                                        
    def __get__(self, ins, cls):        
        return self.data                
                                        
    def __set__(self, ins, v):          
        self.data = v                   
                                        
    def __delete__(self, ins):          
        del self.data                   
                                        
                                        
class A:                                
    p = P(1)                            
                                        
    def __init__(self, v):              
        self.p = v                      
        self.x = v                      
                                        
obj = A(1)                              
print(obj.__dict__)                     
print(obj.p)                            
                                        
obj.p = 2                               
print(obj.p)                            
                                        
del obj.p                               
print(hasattr(obj, 'p'))                
                                        
obj.p = 3                               
print(hasattr(obj, 'p'))                

类属性p相当于代理了对class A中成员p的所有访问、修改、删除操作
p的值实际存储于class P的self.data

要想正确使用Descriptor必须满足这几点:
其中第一点只是用来还原测试代码的输出,实际可以不定义self.p

python:一段代码看懂Descriptor_第3张图片
image.png

Descriptor几个方法的相关参数介绍:

  • 参数ins:为第24行定义的obj
  • 参数cls:为class A
  • 参数v : 将要给p赋的值

扩展:

  1. 类中定义的类函数和方法都是Descriptor
  2. 数据描述符(实现了__set__函数)会覆盖同名实例属性(self.p)
  3. 描述符是通过__getattribute__()方法经由__dict__访问的,所以数据描述符要放在类属性中

你可能感兴趣的:(python:一段代码看懂Descriptor)