先看代码和执行结果,很简单:
image.png然后去掉第18行的注释:
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
Descriptor几个方法的相关参数介绍:
- 参数ins:为第24行定义的obj
- 参数cls:为class A
- 参数v : 将要给p赋的值
扩展:
- 类中定义的类函数和方法都是Descriptor
- 数据描述符(实现了__set__函数)会覆盖同名实例属性(self.p)
- 描述符是通过__getattribute__()方法经由__dict__访问的,所以数据描述符要放在类属性中
网友评论