python - 数据描述符(class 内置 get/set/delete方法 )
数据描述符(class 内置 get/set/del方法 ):
- # 什么是描述符
- # 官方的定义:描述符是一种具有“捆绑行为”的对象属性。访问(获取、设置和删除)它的属性时,实际是调用特殊的方法(_get_(),
- # _set_(),_delete_())。也就是说,如果一个对象定义了这三种方法的任何一种,它就是一个描述符。
- # 更多的理解:
- # 通常情况下,访问一个对象的搜索链是怎样的?比如a.x,首先,应该是查询 a._dict_[‘x’],然后是type(a)._dict_[‘x’],一直
- # 向上知道元类那层止(不包括元类)。如果这个属性是一个描述符呢?那python就会“拦截”这个搜索链,取而代之调用描述符方法
- # (_get_)。
- # 描述符有什么作用?
- # The default behavior for attribute access is to get, set, or delete the attribute from an object's dictionary.
- # For instance, a.x has a lookup chain starting witha.__dict__[‘x'], then type(a).__dict__[‘x'], and continuing
- # through the base classes of type(a) excluding metaclasses. If the looked-up value is an object defining one of
- # the descriptor methods, then Python may override the default behavior and invoke the descriptor method instead.
- # Where this occurs in the precedence chain depends on which descriptor methods were defined.
- # —–摘自官方文档
- # 简单的说描述符会改变一个属性的基本的获取、设置和删除方式。
- # 数据描述符(data descriptor)和非数据描述符(non-data descriptors)
- # 数据描述符:定义了_set_ 和_get_方法的对象
- # 非数据描述符:只定义了_get_方法的对象。通常方法都是非数据描述符。
- # 区别:
- # 1、位于搜索链上的顺序。搜索链(或者优先链)的顺序大概是这样的:数据描述符>实体属性(存储在实体的_dict_中)>非数据描述符。
- # 这个顺序初看起来挺晦涩。解释如下:
- # 获取一个属性的时候:
- # 首先,看这个属性是不是一个数据描述符,如果是,就直接执行描述符的_get_,并返回值。
- # 其次,如果这个属性不是数据描述符,那就按常规去从_dict_里面取。
- # 最后,如果_dict_里面还没有,但这是一个非数据描述符,则执行非数据描述符的_get_方法,并返回。
- # 三个方法(协议):
- # • _get_(self, instance, owner) —获取属性时调用,返回设置的属性值,通常是_set_中的value,或者附加的其他组合值。
- # • _set_(self, instance, value) — 设置属性时调用,返回None.
- # • _delete_(self, instance) — 删除属性时调用,返回None
- # 其中,instance是这个描述符属性所在的类的实体,而owner是描述符所在的类。
- # 为什么要区分数据描述符和非数据描述符?(访问属性的优先级不一样)
- # 1.非数据描述符的获取属性的优先级链是,__getattribute__->找__dict__->找描述符,这条链的规则给了"缓存属性"理论支持(通常是这种)
- # 2.数据描述符,又分为:
- # 2.1 有__get__方法的覆盖型的获取属性的优先级链是,__getattribute__->找描述符,同时__set__方法也会覆盖对实例属性的赋值
- # 操作,就是说任何外部对属性的赋值都将被__set__捕获,同时获取属性也是通过__get__方法获取,__dict__不再起直接作用。
- # 2.2 没有__get__方法的覆盖型的获取属性优先级链是在没有对属性赋值时是__getattribute__->找描述符(返回描述符对象本身)
- # ,对属性赋值了之后是__getattribute__->找__dict__->找描述符
- # 对象属性的访问顺序:
- # ①.实例属性
- # ②.类属性
- # ③.父类属性
- # ④.__getattr__()方法
- #数据描述符 - 优先级顺序:
- # ① __getattribute__(), 无条件调用
- # ② 数据描述符:由 ① 触发调用 (若人为的重载了该 __getattribute__() 方法,可能会调职无法调用描述符)
- # ③ 实例对象的字典(若与描述符对象同名,会被覆盖哦)
- # ④ 类的字典
- # ⑤ 非数据描述符
- # ⑥ 父类的字典
- # ⑦ __getattr__() 方法
- # 描述符有什么用和好处
- # 1)一般情况下不会用到,建议:先定基本的,以后真有需要再扩展。别贪玩。
- # 2)可以在设置属性时,做些检测等方面的处理
- # 3)缓存?
- # 4)设置属性不能被删除?那定义_delete_方法,并raise 异常。
- # 5)还可以设置只读属性
- # 6)把一个描述符作为某个对象的属性。这个属性要更改,比如增加判断,或变得更复杂的时候,所有的处理只要在描述符中操作就行了。
- # #举例:
- # @property
- # #这就是一个数据描述符
- # class Afff():
- # pass
- # 更详尽的示例:
- #摘录于:
- #描述符阐述:
- # https://blog.csdn.net/allenalex/article/details/54097319
- #应用示例:
- # https://www.jb51.net/article/91028.htm
- #优先级阐述:
- # https://www.cnblogs.com/Jimmy1988/p/6808237.html
示例:
- #描述符类(相当于代理)
- #定义为了数据描述符:定义了_set_ 和_get_方法的对象
- class Foo():
- def __get__(self, instance, owner):
- print("执行Foo get方法")
- def __set__(self, instance, value):
- print("执行Foo set方法")
- def __delete__(self):
- print("执行Foo del方法")
- #主要运行的类:
- class Test():
- #类的x属性被Foo代理,所以属性访问优先级也被修改:
- #类属性 > 数据描述符 > 实例属性 > 非实例属性 > __getattr__()
- x = Foo()
- def __init__(self,num):
- self.x = num
- #因为x类属性被Foo代理,触发Foo的set方法,而set方法只是打印了,没有做数据操作,
- abc = Test(100)
- abc.x
- print(abc.__dict__)
- # print输出:-----------
- # 执行Foo set方法
- # 执行Foo get方法
- # {}
- # 执行Foo del方法
- # print输出:-----------
练习:
- #描述符应用- 练习(判断录入类型是否合规)
- class Test():
- def __init__(self, key,type_data):
- self.key = key
- self.type_data = type_data
- def __set__(self, instance, value):
- if isinstance(value,self.type_data):
- instance.__dict__[self.key] = value
- else:
- print("赋值类型错误")
- class People():
- name =Test('name',str)
- def __init__(self,name,old):
- self.name = name
- self.old = old
- #赋值为str类型
- name = 'anec'
- #赋值为int类型
- name2 = 123
- abc = People(name,23)
- abc2 = People(name2,24)
- print(abc.__dict__)
- print(abc2.__dict__)
python - 数据描述符(class 内置 get/set/delete方法 )的更多相关文章
- 二十六. Python基础(26)--类的内置特殊属性和方法
二十六. Python基础(26)--类的内置特殊属性和方法 ● 知识框架 ● 类的内置方法/魔法方法案例1: 单例设计模式 # 类的魔法方法 # 案例1: 单例设计模式 class Teacher: ...
- python数据描述符
Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题苦恼的朋友提 ...
- python小知识-属性查询优先级(如果有同名类属性、数据描述符、实例属性存在的话,实例>类>数据描述符)
https://www.cnblogs.com/Jimmy1988/p/6808237.html https://segmentfault.com/a/1190000006660339 https:/ ...
- python开发函数进阶:内置函数
一,内置函数 #内置的模块#拿过来直接就用的:内置的函数 #!/usr/bin/env python #_*_coding:utf-8_*_ #内置的模块 #拿过来直接就用的:内置的函数 #作用域相关 ...
- Python属性描述符(二)
Python存取属性的方式特别不对等,通过实例读取属性时,通常返回的是实例中定义的属性,但如果实例未曾定义过该属性,就会获取类属性,而为实例的属性赋值时,通常会在实例中创建属性,而不会影响到类本身.这 ...
- Python 2.7 学习笔记 内置语句、函数、标准库
使用任何开发语言进行软件开发,都离不开语言提供的内置库(或Api),甚至说内置库的强大及使用是否方便都会影响大家对开发语言的选择. python语言,一样提供了很多内置的功能,可供开发时使用.主要有如 ...
- python基础12_匿名_内置函数
一个二分查找的示例: # 二分查找 示例 data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35, 36, ...
- Python的描述符
1.描述符的定义 描述符是与特定属性互相绑定的一种协议,通过方法被触发修改属性,这些方法包括__get__(),__set__(),__delete__().将这些方法定义在类中,即可实现描述符 2. ...
- python自动化测试学习笔记-4内置函数,处理json
函数.全局变量 写代码时注意的几点事项: 1.一般写代码的时候尽量少用或不用全局变量,首先全局变量不安全,大家协作的情况下,代码公用容易被篡改,其次全局变量会一直占用系统内容. 2.函数里如果有多个r ...
随机推荐
- BZOJ3261最大异或和——主席树
题目描述 给定一个非负整数序列{a},初始长度为N. 有M个操作,有以下两种操作类型: 1.Ax:添加操作,表示在序列末尾添加一个数x,序列的长度N+1. 2.Qlrx:询问操作,你需要找到一个位置p ...
- TP5报错总结
LNMP一键安装包上部署TP5项目500错误或者空白解决 [问题原因] TP5的入口文件在public下,当他调用类文件时,跨目录所以造成500错误,或者一片空白的问题 [解决方法] 1.public ...
- MarkdownPad 注册码 Version 2.5.0.27920
[注册码] 还望多多支持正版 邮箱地址: Soar360@live.com 授权秘钥: GBPduHjWfJU1mZqcPM3BikjYKF6xKhlKIys3i1MU2eJHqWGImDHzWdD6 ...
- JavaScript 隐式类型转换
JavaScript 隐式类型转换 原文:https://blog.csdn.net/itcast_cn/article/details/82887895 · 1.1 隐式转换介绍 · 1.2 隐式转 ...
- Leetcode 283.移动零 By Python
思路 我们可以用python的list comprehension来取出所以非0的元素,而且这样取出来会保持原有的相对顺序,再统计先后变化的长度,补上相应的0即可 代码 class Solution( ...
- HTM L百度地图API 自定义工具地图实例
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 冬令营前的一些计划&记录
冬令营前的一些计划&记录 计划 yyb发现自己很多以前学过的东西完完全全不记得了,所以在接下来的时间里可能会留下多篇复习向的博客,当然也可能因为觉得没有必要复习而到处乱做题. 现在先大概归类一 ...
- luogu3320 寻宝游戏 (dfs序+倍增lca+set)
一定是从随便某个点开始,然后按着dfs序的顺序跑一圈是最好的 所以说,新加一个点x,就减少了dis(pre,next),增加了dis(pre,x),dis(x,nxt) 删掉一个点同理 这个可以用se ...
- Python进制表示及转换
进制表示: 二进制:>>> abin = 0b1000>>> abin8 八进制:>>> aoct = 0o123 (数字0,字母o)>&g ...
- 【洛谷P4113】采花 HH的项链+
题目大意:静态统计序列区间中出现次数大于等于 2 的颜色数. 题解:类似于HH的项链,只需将 i 和 pre[i] 的关系对应到 pre[i] 和 pre[pre[i]] 的关系即可. 代码如下 #i ...