描述符介绍

描述符本质就是一个新式类,在这个新式类中,至少要实现了__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. [hdu7020]Array

    (这是一个线性的做法) 显然对于合法的区间,众数是唯一的,因此不妨枚举众数,将众数标记为1.其余数标记为-1,此时问题即求有多少个区间和大于0 考虑暴力的做法:从左到右枚举右端点,记当前前缀和为$to ...

  2. [loj2586]选圆圈

    下面先给出比较简单的KD树的做法-- 根据圆心建一棵KD树,然后模拟题目的过程,考虑搜索一个圆 剪枝:如果当前圆[与包含该子树内所有圆的最小矩形]都不相交就退出 然而这样的理论复杂度是$o(n^2)$ ...

  3. [noi109]排队

    题目要求其实相当于要让大于和小于m的数的个数都不超过n/2,因此当要对一个数处理时,要么把它改成m,要么不作修改,根据这个贪心就可以完成了. 1 #include<bits/stdc++.h&g ...

  4. SimpleNVR安防监控RTSP/FLV/HLS直播流服务如何分权限添加用户指定通道观看

    背景分析 随着SimpleNVR的用户越来越多,很多客户反馈给了我们很宝贵的简易以及用户体验.在此非常感谢大家对我们的支持.其中很多客户不想把所有的视频直播展现出来,想分权限添加新用户,指定通道让其观 ...

  5. HDU 7066 - NJU emulator(构造题)

    题面传送门 提供一种不同于官方题解.需要的操作次数比官方题解多(官方题解大概是 \(2\times 16\),我这大概是 \(3\times 16\)),但能通过此题的做法. 首先我们考虑一个暴力,我 ...

  6. 如何从vcf文件中批量提取一系列基因的SNP位点?

    目录 需求 示例文件 代码实现 补充说明 需求 客户的一个简单需求: 我有一批功能基因位点,想从重测序的群体材料中找到这些位点,如何批量快速获得? 示例文件 gene.txt test.vcf 代码实 ...

  7. MetaboAnalyst的多组学分析

    MetaboAnalyst是做代谢的R包,功能十分强大.也开发了web版本,代谢组学的分析这里不介绍,主要讲讲它开发的多组学分析的相关内容. 既然是做代谢的工具,即使是增加了多组学内容,肯定也是以代谢 ...

  8. ss 显示socket状态

    ss ===show socket用于显示socket状态 所有的TCP sockets 所有的UDP sockets 所有ssh/ftp/ttp/https持久连接 所有连接到Xserver的本地进 ...

  9. R 多图间距调整

    在R中多图画到一起的时候,各图间距通常默认的较远. 如下图: 1 par(mfcol=c(2,1)) 2 plot(1:100) 3 plot(1:100) 调整图片间距这时我们要用到par()函数中 ...

  10. linux 线程函数小结

    由于主线程已经开始跑了,次线程还在使用串口打印需要一点时间,因此打印的都是重复的. #include "pthread.h" #include "stdio.h" ...