描述符介绍

描述符本质就是一个新式类,在这个新式类中,至少要实现了__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:要严格遵循该优先级,优先级由高到底分别是

  1. 类属性
  2. 数据描述符
  3. 实例属性
  4. 非数据描述符
  5. 找不到的属性触发 __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 的描述符协议的更多相关文章

  1. 杂项之python描述符协议

    杂项之python描述符协议 本节内容 由来 描述符协议概念 类的静态方法及类方法实现原理 类作为装饰器使用 1. 由来 闲来无事去看了看django中的内置分页方法,发现里面用到了类作为装饰器来使用 ...

  2. Iterator Protocol - Python 描述符协议

    Iterator Protocol - Python 描述符协议 先看几个有关概念, iterator 迭代器, 一个实现了无参数的 __next__ 方法, 并返回 '序列'中下一个元素,在没有更多 ...

  3. Descriptor - Python 描述符协议

    描述符(descriptor) descriptor 是一个实现了 __get__. __set__ 和 __delete__ 特殊方法中的一个或多个的. 与 descriptor 有关的几个名词解释 ...

  4. python理解描述符(descriptor)

    Descriptor基础 python中的描述符可以用来定义触发自动执行的代码,它像是一个对象属性操作(访问.赋值.删除)的代理类一样.前面介绍过的property是描述符的一种. 大致流程是这样的: ...

  5. Python属性描述符(一)

    描述符是对多个属性运用相同存取逻辑的一种方式,,是实现了特性协议的类,这个协议包括了__get__.__set__和__delete__方法.property类实现了完整的描述符协议.通常,可以只实现 ...

  6. python数据描述符

    Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题苦恼的朋友提 ...

  7. 【python】描述符descriptor

    开始看官方文档,各种看不懂,只看到一句Properties, bound and unbound methods, static methods, and class methods are all ...

  8. python Descriptor (描述符)

    简介: python 描述符是新式类(继承自object)中的语言协议,基于描述符可以提供更佳优雅的解决方案. python的classmethod, staticmethod, property都是 ...

  9. python - 数据描述符(class 内置 get/set/delete方法 )

    数据描述符(class 内置 get/set/del方法 ): # 什么是描述符 # 官方的定义:描述符是一种具有“捆绑行为”的对象属性.访问(获取.设置和删除)它的属性时,实际是调用特殊的方法(_g ...

随机推荐

  1. python实现Canny边缘检测

    一,定义与概述 使用图像梯度的算法,在有些场景不适用,如检测大量头发边缘,边缘不够细腻.所以有人提出了Canny算法! 非极大值抑制,保留极大值 参考:https://www.cnblogs.com/ ...

  2. Java JDBC 理论笔记

    一.JDBC常用接口.类介绍 JDBC提供对独立于数据库统一的API,用以执行SQL命令.API常用的类.接口如下: DriverManager 管理JDBC驱动的服务类,主要通过它获取Connect ...

  3. 分布式事务(七)之Seata简介

    在前面的文章中,我们介绍了分布式事务的概念以及一些解决方案.fenSeata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata将为用户提供了AT.TCC.SAGA和 ...

  4. 为什么前端H5工程师工资那么高?

    目前,企业对于html5前端开发人才需求量非常大,小到企业网站.个人主页,大到政府部门,都是通过网站向外界展示形象.传播信息,网站离不开HTML5前端开发人员,所以学习html5前端开发在当前社会非常 ...

  5. CF1463E Plan of Lectures

    考虑我们两种操作: 我们把第一种操作在\(x\to y\)连一条权为-1的边. 第二种操作\(x\to y\)连-1,\(y\to x\)连1的边. 当无法操作则是环里有负环. 否则我们把第二种操作涉 ...

  6. 毕业设计之mysql+主从复制+keepalived

    环境介绍 mysql_VIP:192.168.111.123 mysql_M!:192.168.111.151 mysql_M2:192.168.111.152 安装mysql可以查看 两个数据库都需 ...

  7. vim ——批量注释

    1111. ctrl+v进入列编辑模式,在编辑模式中,在行间上下移动光标,选择需要编辑哪些行的对应的列,之后使用I(大写)进入列插入.插入注释符,按两次Esc退出列编辑模式即可实现多行注释 删除注释: ...

  8. Oracle--计算某一日期为一年中的第几周

    我自己实现的脚本: select T31267.CREATED_DATE as F31265, (select to_char(to_date(T31267.CREATED_DATE,'yyyy-mm ...

  9. lua table与json的之间的互相转换高性能c++实现

    请自行约束两种语言数据结构语法上的不同,避开如下问题: 1.json本身不约束key是否符合一个编程语言中的变量名,所以编写用于和编程语言数据结构交互的json代码时应该注意key是否正确. 2.lu ...

  10. 云原生时代,为什么基础设施即代码(IaC)是开发者体验的核心?

    作者 | 林俊(万念) 来源 |尔达 Erda 公众号 从一个小故事开始 你是一个高级开发工程师. 某天,你自信地写好了自动煮咖啡功能的代码,并在本地调试通过.代码合并入主干分支后,你准备把服务发布到 ...