一文掌握 Python 的描述符协议
描述符介绍
描述符本质就是一个新式类,在这个新式类中,至少要实现了__get__(),__set__(),__delete__()中的一个。这也被称为描述符协议。
class Myclass(object):
def __get__(self, instance, owner):
'''调用一个属性时触发'''
pass
def __set__(self, instance, value):
'''为一个属性赋值时触发'''
pass
def __delete__(self, instance):
'''使用del删除属性时触发'''
pass
描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)
数据描述符
至少实现了__get__()和__set__()
class Myclass(object):
def __set__(self, instance, value):
print('set')
def __get__(self, instance, owner):
print('get')
非数据描述符
没有实现__set__()
class Myclass(object):
def __get__(self, instance, owner):
print('get')
注1:必须把描述符定义成这个类的类属性,不能为定义到构造函数中
注2:要严格遵循该优先级,优先级由高到底分别是
- 类属性
- 数据描述符
- 实例属性
- 非数据描述符
- 找不到的属性触发
__getattr__()
例1:利用描述符实现参数类型检测
class Typed(object):
def __init__(self, key, exc_type):
self.key = key
self.exc_type = exc_type
def __get__(self, instance, owner):
return instance.__dict__[self.key]
def __set__(self, instance, value):
# 先判断类型是否为期望类型,如果不是则报错
if not isinstance(value, self.exc_type):
raise TypeError
instance.__dict__[self.key] = value
def __delete__(self, instance):
instance.__dict__.pop(self.key)
class Person(object):
name = Typed('name', str)
age = Typed('age', int)
def __init__(name, age):
self.name = name
self.age = age
例2:使用描述符自定制property
class Lazyproperty(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
'''使用该方法实现非数据描述符'''
# 当使用类调用属性时,返回自身
if not isinstance:
return self
ret = self.func(instance)
# 如果该属性计算过程较为复杂,可以为实例设置属性,以后就不用重复计算了
# 原因是因为非数据描述符优先级低于实例属性,下次调用的时候会优先从实例属性字典中查找
# 而不会再次调用本方法重复计算
setattr(instance, self.func.__name__, ret)
return ret
class Room(object):
def __init__(self, name, width, length):
self.name = name
self.width = width
self.length = length
@Lazyproperty # 这一步相当于定义了一个类属性 -> area = Lazyproperty(area)
def area(self):
return self.width * self.length
一文掌握 Python 的描述符协议的更多相关文章
- 杂项之python描述符协议
杂项之python描述符协议 本节内容 由来 描述符协议概念 类的静态方法及类方法实现原理 类作为装饰器使用 1. 由来 闲来无事去看了看django中的内置分页方法,发现里面用到了类作为装饰器来使用 ...
- Iterator Protocol - Python 描述符协议
Iterator Protocol - Python 描述符协议 先看几个有关概念, iterator 迭代器, 一个实现了无参数的 __next__ 方法, 并返回 '序列'中下一个元素,在没有更多 ...
- Descriptor - Python 描述符协议
描述符(descriptor) descriptor 是一个实现了 __get__. __set__ 和 __delete__ 特殊方法中的一个或多个的. 与 descriptor 有关的几个名词解释 ...
- python理解描述符(descriptor)
Descriptor基础 python中的描述符可以用来定义触发自动执行的代码,它像是一个对象属性操作(访问.赋值.删除)的代理类一样.前面介绍过的property是描述符的一种. 大致流程是这样的: ...
- Python属性描述符(一)
描述符是对多个属性运用相同存取逻辑的一种方式,,是实现了特性协议的类,这个协议包括了__get__.__set__和__delete__方法.property类实现了完整的描述符协议.通常,可以只实现 ...
- python数据描述符
Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题苦恼的朋友提 ...
- 【python】描述符descriptor
开始看官方文档,各种看不懂,只看到一句Properties, bound and unbound methods, static methods, and class methods are all ...
- python Descriptor (描述符)
简介: python 描述符是新式类(继承自object)中的语言协议,基于描述符可以提供更佳优雅的解决方案. python的classmethod, staticmethod, property都是 ...
- python - 数据描述符(class 内置 get/set/delete方法 )
数据描述符(class 内置 get/set/del方法 ): # 什么是描述符 # 官方的定义:描述符是一种具有“捆绑行为”的对象属性.访问(获取.设置和删除)它的属性时,实际是调用特殊的方法(_g ...
随机推荐
- 使用 docker + verdaccio 搭建npm私有仓库
本文介绍如何使用 verdaccio 搭建私有npm仓库,以及使用 docker 时如何映射到本地目录,方便简单对仓库进行各种操作.系统环境是 Linux. verdaccio verdaccio 是 ...
- android测试之monkey测试
1.首先安装SDK包 2.配置环境变量 3.打开CMD命令窗口,查看是否安装成功 命令:adb version 4.要做monkey测试的安卓包名,获取方式如下(必须启动要获取报名的app) 1.ad ...
- 干掉if-else的方法
策略模式+工厂方法消除if else 假设需求为,根据不同勋章类型,处理相对应的勋章服务,优化前有以下代码: String medalType = "guest"; if (&qu ...
- go 自定义http.Client - 动态修改请求Body
前言 在对接Alexa Smart Home时,有的请求Payload中需要传入Access Token,但是这个Token是由OAuth2 Client管理的,封装Payload时并不知道Acces ...
- 【2020五校联考NOIP #7】伟大的卫国战争
题面传送门 题意: 数轴上有 \(n\) 个点,现在要在它们之间连 \(m\) 条边,第 \(i\) 条边连接 \(a_i,b_i\) 两个点. 现在你要钦定每条边连在数轴的上方还是下方,使得任意两条 ...
- Codeforces 453E - Little Pony and Lord Tirek(二维线段树+ODT)
Codeforces 题目传送门 & 洛谷题目传送门 一道难度 *3100 的 DS,而且被我自己搞出来了! 不过我终究还是技不如人,因为这是一个 \(n\log^2n\) + 大常数的辣鸡做 ...
- 使用CNVnator分析动植物群体拷贝数变异CNV
目录 1.安装 2.测试 3.动植物群体检测CNV 知名的拷贝数变异分析工具几乎都是为人类变异检测开发,对于动植物重测序分析有些尴尬.不过好在植物群体研究不必那么精细,用同样的工具也可做分析. 地址: ...
- window修改dns本地文件
文件地址: C:\Windows\System32\drivers\etc 先修改权限: 最后用记事本打开编辑保存即可
- Python基础之赋值与注释
目录 1. 花式赋值 1.1 链式赋值 1.2 交叉赋值 1.3 交叉赋值(解压缩) 2. 注释 2.1 单行注释 2.2 多行注释 1. 花式赋值 1.1 链式赋值 a = 10 b = 10 c ...
- 学习java的第十四天
一.今日收获 1.完成了手册第二章没有验证完成的例题 2.预习了第三章的算法以及for语句与if语句的用法 二.今日难题 1.验证上出现问题,没有那么仔细. 2.第二章还有没有完全理解的问题 三.明日 ...