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 __get__(self,instance,own=None):
if instance is None:
return self
if self.getf is None:
raise AttributeError
return self.getf(instance)
def __set__(self,instance,value):
if self.setf is None:
raise AttributeError
self.setf(instance,value)
def __del__(self,instance):
if self.delf is None:
raise AttributeError
self.delf(instance)
class StaticMethod(object):
def __init__(self,func):
self.func=func
def __get__(self,instance,own=None):
return self.func
class ClassMethod(object):
def __init__(self,func):
self.func=func
def __get__(self,instance,own=None):
if own is None:
own=type(instance)
def callfunc(*args):
return self.func(own,*args)
return callfunc
为属性值设置别名
有时候你想用一个属性名作为另一个属性名的别名,比如设置一些属性的默认值必须和其他属性的当前值一样,而且还需要独立的设置和删除。
class DefaultAlias(object):
def __init__(self,name):
self.name=name
def __get__(self,instance,own):
if instance is None: #类属性访问时
return self
return getattr(instance,self.name).title()
class Person(object):
def __init__(self,name,aliasname=None):
self.name=name
if aliasname is not None:
self.aliasname=aliasname
aliasname=DefaultAlias('name')
>>> p=Person('sam')
>>> p.aliasname
'Sam'
>>> p.aliasname='jack'
>>> p.aliasname
'jack'
>>> del p.aliasname
>>> p.aliasname
'Sam'
这样就为属性name设置了一个别名aliasname,或者说把aliasname的值存储在了name中。DefaultAlias并不是数据描述符,因为它没有__set__方法,而是一个non-data描述符。所以我们给一个实例属性赋值时(p.aliasname='jack'),实例会正常地记录属性,而且实例属性会覆盖掉类属性。这样aliasname属性就能单独的设置而不影响name属性了。当我们del p.aliasname时,删除了实例的属性,类属性又会再次显现出来。
对于某些开发的类,如果要保持后续版本的兼容性,可以用新名称来命名方法和属性,同时保留旧名字的可用性。
class OldAlias(object):
def __init__(self,name,oldname):
self.name=name
self.oldname=oldname
def _warn(self):
print 'use %r,not %r'%(self.name,self.oldname)
def __get__(self,instance,own):
self._warn()
if instance is None:
return self
return getattr(instance,self.name)
def __set__(self,instance,value):
self._warn()
setattr(instance,self.name,value)
def __del__(self,instance):
self._warn()
delattr(instance,self.name)
class NewClass(object):
def __init__(self,newname):
self.newname=newname
oldname=OldAlias('newname','oldname')
>>> c=NewClass('a')
>>> c.oldname
use 'newname',not 'oldname'
'a'
使用这个类的旧代码会使用类属性oldname,同时一个警告信息被打印,鼓励用户使用新属性newname。
缓存属性值
根据需求计算实例属性或类属性的值,并提供自动化的缓存。
class CachedAttribute(object):
def __init__(self,method,name=None):
self.method=method
self.name=name if name else method.__name__
def __get__(self,instance,own):
if instance is None:
return self
result=self.method(instance)
setattr(instance,self.name,result)
return result
class MyObject(object):
def __init__(self,n):
self.n=n
@CachedAttribute
def square(self):
return self.n*self.n
>>> m=MyObject(2)
>>> m.square
4
>>> m.n=5
>>> m.square
4
>>> del m.square
>>> m.square
25
在首次访问m.square后,square属性就被缓存在实例m中,当改变实例属性n时,square属性不会改变。如果需要清除缓存,del m.square即可,再次访问m.square属性square的值会被再次计算。
缓存类属性:
class CachedClassAttribute(CachedAttribute):
def __get__(self,instance,own):
return super(CachedClassAttribute,self).__get__(own,own)
class MyClass(object):
class_attr=24
@CachedClassAttribute
def square(cls):
return cls.class_attr*cls.class_attr
这样类的所有实例都有同样的缓存值了:
>>> a=MyClass()
>>> b=MyClass()
>>> a.square
>>> print a.square
576
>>> print b.square
576
>>> print MyClass.square
576
python描述符descriptor(二)的更多相关文章
- Python 描述符(descriptor) 杂记
转自:https://blog.tonyseek.com/post/notes-about-python-descriptor/ Python 引入的“描述符”(descriptor)语法特性真的很黄 ...
- python描述符descriptor(一)
Python 描述符是一种创建托管属性的方法.每当一个属性被查询时,一个动作就会发生.这个动作默认是get,set或者delete.不过,有时候某个应用可能会有 更多的需求,需要你设计一些更复杂的动作 ...
- python描述符 descriptor
descriptor 在python中,如果一个新式类定义了__get__, __set__, __delete__方法中的一个或者多个,那么称之为descriptor.descriptor通常用来改 ...
- python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解
1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题 ...
- Python描述符 (descriptor) 详解
1.什么是描述符? python描述符是一个“绑定行为”的对象属性,在描述符协议中,它可以通过方法重写属性的访问.这些方法有 __get__(), __set__(), 和__delete__().如 ...
- Python 描述符(Descriptor) 附实例
在 Python 众多原生特性中,描述符可能是最少被自定义的特性之一,但它在底层实现的方法和属性却无时不刻被使用着,它优雅的实现方式体现出 Python 简洁之美. 定义 一个描述符是一个有" ...
- Python 描述符 (descriptor)
1.什么是描述符? 描述符是Python新式类的关键点之一,它为对象属性提供强大的API,你可以认为描述符是表示对象属性的一个代理.当需要属性时,可根据你遇到的情况,通过描述符进行访问他(摘自Pyth ...
- 【python】描述符descriptor
开始看官方文档,各种看不懂,只看到一句Properties, bound and unbound methods, static methods, and class methods are all ...
- 杂项之python描述符协议
杂项之python描述符协议 本节内容 由来 描述符协议概念 类的静态方法及类方法实现原理 类作为装饰器使用 1. 由来 闲来无事去看了看django中的内置分页方法,发现里面用到了类作为装饰器来使用 ...
随机推荐
- vs2012找不到system web optimization命名空间
今天新装了vs2012,安装完成后,创建了一个mvc4应用程序,创建生成出现了几个错误.通过错误我们的解决方案就是去找引用不到的路径,如何在vs2012中实现呢? 在工具栏中找工具--库程序包管理器- ...
- 从客户端中检测到有潜在危险的 Request.Form 值] 处理办法
当asp.net提交<>这些字符到aspx页面时,如果未设置 validaterequest="false",就会出现错误:从客户端(<?xml version= ...
- mysql innodb 数据打捞(一)innodb 页面结构特征
如果文件系统损坏或意外删除了数据库文件,只要磁盘空间没有被覆盖,其实数据都还在磁盘的扇区中,还是可以恢复出来的,有些通用的文件恢复工具好象也可以恢复文件 ,但这里要研究的是在通用文件 恢复工具失效的时 ...
- 关于C#虚函数和构造函数的一点理解
虚函数感觉总是很神秘,在本质的原理上一直也没有弄得很透彻,今天又有一点的新的感悟,纪录下来,有时间的话可以去研究一下C++对象模型 using System; using System.Collect ...
- 栈(顺序存储)C++模板实现
#include <iostream> using namespace std; template <typename T> class stack{ private: int ...
- Java添加事件的四种方式
Java添加事件的几种方式(转载了codebrother的文章,做了稍微的改动) /** * Java事件监听处理——自身类实现ActionListener接口,作为事件监听器 * * @author ...
- source和.命令的区别
source FileName 作用:在当前bash环境下读取并执行FileName中的命令. 注:该命令通常用命令“.”来替代. 如:source .bash_rc 与 . .bash_rc 是等效 ...
- 正确理解javascript的this关键字
javascript有this关键字,它和javascript的执行上下文有着密切的关系,就是说this具体指代什么要根据它的上下文来判断. 一.this和对象的关系 var Person={ ...
- 《jQuery、jQuery UI及jQuery Mobile技巧与示例》勘误收集
此书由程学彬 (http://weibo.com/ironbin)和我合译完成,此篇博客作为勘误收集而用,若译文有误或者有任何疑问,欢迎留下评论,或者给我发邮件(地址:gzooler@gmail.co ...
- 《jQuery UI开发指南》勘误收集
此书由罗晴明 (http://weibo.com/sunnylqm)和我合译完成,此篇博客作为勘误收集而用,若译文有误或者有任何疑问,欢迎留下评论,或者给我发邮件(地址:gzooler@gmail.c ...