数据描述符与非数据描述符
来源:互联网 发布:dx修复软件 编辑:程序博客网 时间:2024/06/04 23:21
起因是前两天在煎蛋看到这个段子:
所以我就问了下友人们,什么是“非数据描述符”,然后友人给了我这个:
class A(object): name = "haha1"print("此时A这个类的name属性是haha1")print(A.name)print("a是A的实例")a = A()print("这里虽然是输出了haha1, 但是实际上a并没有这个name属性, 而是因为向上搜索到了类的属性, 所以'继承'了出来")print(a.name)## print("这里的'赋值', 显然不会'覆盖'掉类A的属性, 而是给对象a增加了一个name属性, 并且把值赋成haha2")a.name = "haha2"print("类A的name属性不会变")print(A.name)print("对象a得到了name属性")print(a.name)print("删除a的name属性")del a.nameprint("a没有了属性name, 因此再次去'继承'其类的name属性")print(a.name)print("\n************************************************\n")## 实现一个特殊类, 并定义__get__和__set__方法class TestDescriptor(object): def __get__(self, obj, type = None): pass def __set__(self, obj, val): passclass B(object): ## 把类B的一个属性设置成上面特殊类的对象 name = TestDescriptor()## print("实例化类B")b = B()print("类B有name属性, 是上面那个特殊类的对象, 但却输出None")print(B.name)print("对象b没有name属性, 应该'继承'类B的属性, 但却输出None")print(b.name)## print("给对象b增加name属性haha3")b.name = "haha3"print("对象b新增了name属性, 值为haha3, 但却输出None")print(b.name)print("\n************************************************\n")## 在上面的特殊类的基础上, 增加一些__get__和__set__的输出class TestDescriptor2(object): def __get__(self, obj, type = None): print("get is called.") def __set__(self, obj, val): print("set is called.")class B2(object): ## 把类B的一个属性设置成上面特殊类的对象 name = TestDescriptor2()## print("实例化类B")b2 = B2()print("类B有name属性, 是上面那个特殊类的对象, 但却输出None, 实际在获取类B的name属性时, 调用了特殊类的__get__方法")print(B2.name)print("对象b没有name属性, 应该'继承'类B的属性, 但却输出None, 实际在获取类B的name属性时, 调用了特殊类的__get__方法")print(b2.name)print("给对象b增加name属性haha3, 在设置对象b的name属性时, 调用了特殊类的__set__方法")b2.name = "haha3"print("对象b新增了name属性, 值为haha3, 但却输出None, 还是调用了特殊类的__get__方法")print(b2.name)print("\n************************************************\n")## 在上面的特殊类的基础上, 再增加一些返回class TestDescriptor3(object): def __init__(self): self.temp = ''; def __get__(self, obj, type = None): print("get is called.") return self.temp + " -> after get" def __set__(self, obj, val): print("set is called.") self.temp = val + " -> after set" print(self.temp)class B3(object): ## 把类B的一个属性设置成上面特殊类的对象 name = TestDescriptor3()## print("实例化类B")b3 = B3()print("给对象b增加name属性haha3, 在设置对象b的name属性时, 调用了特殊类的__set__方法")print("调用了__set__, 于是特殊类的selt.temp被赋值")b3.name = "haha3"print("对象b新增了name属性, 值为haha3, 但却输出None, 还是调用了特殊类的__get__方法")print("调用了__get__, 于是特殊类的selt.temp再次被赋值")print(b3.name)## 综上, 在这个特殊类中, 可以对'获取'和'设置'对象的属性做一些中间工作, 这个特殊的中间类, 就被称作数据描述符## 下面是网上抄的定义## 在访问属性的过程中, 遵循一个优先级顺序## 1. 类## 2. 数据描述符## 3. 对象## 4. 非数据描述符## 5. def __getattr__(self, attr) 方法## 实现了__get__, __set__, __del__方法的类属性, 叫做数据描述符## __get__标准定义是 __get__(self, obj, type=None) 三个参数分别为实例/访问方法/None## __set__标准定义是 __set__(self, obj, val) 三个参数分别为实例/访问方法/set的值## __del__标准定义是 __del__(self, obj) 两个参数分别为实例/访问方法print("\n************************************************\n")## 根据上面的这个定义, 实例数据是可以覆盖非数据描述符的, 但不可以覆盖数据描述符## 只有__get__, 是非数据描述符class C1(object): def __get__(self, obj, type = None): print("get is called.")## 有__get__和__set__, 是非数据描述符class C2(object): def __get__(self, obj, type = None): print("get is called.") def __set__(self, obj, val): print("set is called.")class D1(object): name = C1()class D2(object): name = C2()d1 = D1()print("给对象d1设置name属性的值")d1.name = "haha5"print("实例数据覆盖了非数据描述符, 不会调用__get__")print(d1.name)d2 = D2()print("给对象d2设置name属性的值")d2.name = "haha5"print("实例数据不能覆盖数据描述符, 继续调用__get__")print(d2.name)
好吧……我不会python,我突然不想知道什么是“非数据描述符”了……
祝友人新婚快乐……
阅读全文
0 0
- 数据描述符与非数据描述符
- 数据描述与联系
- 数据描述
- JavaScript---Object.defineProperty()与两种属性描述符简介->数据\存取描述符
- 文件描述符与进程描述符
- 描述符与Apache
- 描述符与property
- 数据描述传输机制
- 数据的描述方式
- 支持向量数据描述
- 数据联系的描述
- 数据描述性分析
- 统计分析基础-描述数据
- 用数据描述故事
- 数据段描述符和代码段描述符(一)
- 数据段描述符和代码段描述符(二)
- 数据预处理之数据描述
- 数据挖掘2-数据描述
- Easyui中DataGrid组件重复请求问题
- 第13届湖南省大学生程序竞赛总结
- 马上要入坑的小白前来报道
- es2015学习笔记<经典入门>
- 字符串方法
- 数据描述符与非数据描述符
- 图像处理与机器视觉(1)
- leetcode 85. Maximal Rectangle 最大子矩阵
- Maven学习笔记---传递依赖冲突解决
- 3S基础知识:用MapX快速开发
- java List 排序 Collections.sort()
- nginx及apache不缓存配置
- 安卓系统修改常用命令
- AgentWeb三方android web开源库的理解和认识