python描述符 descriptor

在python中,如果一个新式类定义了__get__, __set__, __delete__方法中的一个或者多个,那么称之为descriptor。descriptor通常用来改变默认的属性访问(attribute lookup), 前提是descriptor的实例是类的属性(class attribute)。下面的代码展示了简单的用法

 1 # -*- coding: utf-8 -*- 2 class Des(object): 3     def __init__(self, init_value): 4         self.value = init_value 5   6     def __get__(self, instance, typ): 7         print(‘call __get__‘, instance, typ) 8         return self.value 9  10     def __set__(self, instance, value):11         print (‘call __set__‘, instance, value)12         self.value = value13  14     def __delete__(self, instance):15         print (‘call __delete__‘, instance)16  17 class Widget(object):18     t = Des(1)19  20 def main():21     w = Widget()22     print type(w.t)23     w.t = 124     print w.t, Widget.t25     del w.t26     print w.t27  28  29 if __name__==‘__main__‘:30     main()

这三个特殊的函数签名是这样的:

  • object.__get__(selfinstanceowner):return value
  • object.__set__(selfinstancevalue):return None
  • object.__delete__(selfinstance): return None

形参中,instance是类的实例(w), owner是类(widget)

w.t 等价于 Pro.__get__(t, w, Widget).而Widget.t 等价于 Pro.__get__(t, None, Widget)

descriptor主要用于控制属性的访问(读、写、删除)。python doc里面有写到,property()就是一个data descriptor实现(可参见这个文档)。 python2.2中,大量新式类的实现都基于descriptor  

They are the mechanism behind properties, methods, static methods, class methods, and super(). They are used throughout Python itself to implement the new style classes introduced in version 2.2.

在实践中,我们有可能需要监控或者限制对属性的访问。比如,对象的一个属性被“莫名其妙”地修改了,但搜索所有文件有找不到可以的地方,那么我们可以通过__setattr__(self, k, v)方法,对于我们关心的 k 打印出调用栈。另外,也可以用property,示例代码如下:

 1 class TestProperty(object): 2     def __init__(self): 3         self.__a = 1 4   5     @property 6     def a(self): 7         return self.__a 8   9     @a.setter10     def a(self, v):11         print(‘output call stack here‘)12         self.__a = v13  14 if __name__==‘__main__‘:15     t = TestProperty()16     print t.a17     t.a = 218     print t.a

如果需要禁止对属性赋值,或者对新的值做检查,也很容易修改上面的代码实现

既然有了property,那什么时候还需要descriptor呢?property最大的问题在于不能重复使用,即对每个属性都需要property装饰,代码重复冗余。而使用descriptor,把相同的逻辑封装到一个单独的类,使用起来方便多了。

笔者之前看bottle.py源码的时候,看到这么一个descriptor使用,部分源代码和测试代码如下:

 1 import functools, time 2 class cached_property(object): 3     """ A property that is only computed once per instance and then replaces 4         itself with an ordinary attribute. Deleting the attribute resets the 5         property. """ 6  7     def __init__(self, func): 8         functools.update_wrapper(self, func) 9         self.func = func10 11     def __get__(self, obj, cls):12         if obj is None: return self13         value = obj.__dict__[self.func.__name__] = self.func(obj)14         return value15 16 class TestClz(object):17     @cached_property18     def complex_calc(self):19         print ‘very complex_calc‘20         return sum(range(100))21 22 if __name__==‘__main__‘:23     t = TestClz()24     print ‘>>> first call‘25     print t.complex_calc26     print ‘>>> second call‘27     print t.complex_calc

运行结果如下:

>>> first call

very complex_calc

4950

>>> second call

4950

时间: 2024-11-04 20:23:24

python描述符 descriptor的相关文章

python描述符descriptor(二)

python内置的描述符 python有些内置的描述符对象,property.staticmethod.classmethod,python实现如下: class Property(object): def __init__(self,getf,setf,delf,doc): self.getf=getf self.setf=setf self.delf=delf self.doc=doc def __set__(self,instance,own=None): if instance is N

python描述符descriptor(一)

Python 描述符是一种创建托管属性的方法.每当一个属性被查询时,一个动作就会发生.这个动作默认是get,set或者delete.不过,有时候某个应用可能会有 更多的需求,需要你设计一些更复杂的动作.最好的解决方案就是编写一个执行符合需求的动作的函数,然后指定它在属性被访问时运行.一个具有这种功能的对象 称为描述符.描述符是python方法,绑定方法,super,property,staticmethod和classmethod的实现基础. 1.描述符协议 描述符descriptor就是一个表

Python 描述符(descriptor) 杂记

转自:https://blog.tonyseek.com/post/notes-about-python-descriptor/ Python 引入的“描述符”(descriptor)语法特性真的很黄很暴力,我觉得这算是 Python 对象模型的核心成员之一.Python 语言设计的紧凑很大程度上得益于它.所以写一篇笔记文记录关于描述符我知道的一切. 低层 - 纯纯的描述符 纯纯的描述符很纯,基于类中定义的 __get__ . __set__ . __delete__ 三个特殊的方法.实现了这三

杂项之python描述符协议

杂项之python描述符协议 本节内容 由来 描述符协议概念 类的静态方法及类方法实现原理 类作为装饰器使用 1. 由来 闲来无事去看了看django中的内置分页方法,发现里面用到了类作为装饰器来使用,由于之前就看到过这一类的用法,但是一直没有明白具体是如何实现的,今天本着打破砂锅问到底的精神去网上搜资料,在这里不得不吐槽下百度搜索的垃圾了.....竞价排名做的那么6,搜一些技术文档.....各种坑爹...就是找不到想要的资源...于是FQ上google搜了搜,找到了python官网的文档...

转载python描述符介绍

来源:http://www.ibm.com/developerworks/cn/opensource/os-pythondescriptors/ 简介 Python 2.2 引进了 Python 描述符,同时还引进了一些新的样式类,但是它们并没有得到广泛使用.Python 描述符是一种创建托管属性的方法.除了其他优点外,托管属性还用于保护属性不受修改,或自动更新某个依赖属性的值. 描述符增加了对 Python 的理解,改善了编码技能.本文介绍了描述符协议,并演示了如何创建和使用描述符. 描述符协

Iterator Protocol - Python 描述符协议

1 Iterator Protocol - Python 描述符协议 2 3 先看几个有关概念, 4 iterator 迭代器, 5 一个实现了无参数的 __next__ 方法, 并返回 '序列'中下一个元素,在没有更多的元素可返回的时候 raises StopIteration 的对象, 6 被称为 iterator(迭代器). 7 在 python 中, 迭代器 'iterator' 同时也实现了 __iter__ 方法, 故 iterators are iterable. 8 经典迭代器

python——描述符

1.什么是描述符? python描述符是一个“绑定行为”的对象属性,在描述符协议中,它可以通过方法重写属性的访问.这些方法有 __get__(), __set__(), 和__delete__().如果这些方法中的任何一个被定义在一个对象中,这个对象就是一个描述符. 2.讲解描述符前,先看一下属性:__dict__ (每个对象均具备该属性) 作用:字典类型,存放本对象的属性,key(键)即为属性名,value(值)即为属性的值,形式为{attr_key : attr_value} 对象属性的访问

Python描述符的使用

Python描述符的使用 前言 作为一位python的使用者,你可能使用python有一段时间了,但是对于python中的描述符却未必使用过,接下来是对描述符使用的介绍 场景介绍 为了引入描述符的使用,我们先设计一个非常简单的类: class Product(): def __init__(self,name,quantity,price): self.name = name self.quantity = quantity self.price = price 这是一个商品类,存储该商品的名称

Python描述符(descriptor)解密

Python中包含了许多内建的语言特性,它们使得代码简洁且易于理解.这些特性包括列表/集合/字典推导式,属性(property).以及装饰器(decorator).对于大部分特性来说,这些"中级"的语言特性有着完善的文档,并且易于学习. 但是这里有个例外,那就是描述符.至少对于我来说,描述符是Python语言核心中困扰我时间最长的一个特性.这里有几点原因如下: 有关描述符的官方文档相当难懂,而且没有包含优秀的示例告诉你为什么需要编写描述符(我得为Raymond Hettinger辩护一