起步

我们希望将一个只读的属性定义为 property 属性方法,只有在访问它时才进行计算,但是,又希望把计算出的值缓存起来,不要每次访问它时都重新计算。

解决方案

定义一个惰性属性最有效的方法就是利用描述符类来完成它,示例如下:

class lazyproperty:

def __init__(self, fun):

self.fun = fun

def __get__(self, instance, owner):

if instance is None:

return self

value = self.fun(instance)

setattr(instance, self.fun.__name__, value)

return value

要使用这个工具,可以像下面的方式来使用它:

class Circle:

def __init__(self, radius):

self.radius = radius

@lazyproperty

def area(self):

print('Computing area')

return 3.1415 * self.radius ** 2

c = Circle(5)

print(c.area)

print(c.area)

可以看出,这里的实例方法 area() 只会被调用一次。

为什么会这样

如果类中定义了 __get__()、__set__() 、__delete__() 中的任何方法,那么这个就被成为描述符(descriptor)。

一般情况下(我是说一般情况下),访问属性的默认行为是从对象的字典中获取,并沿着一个查找链的顺序进行搜索,比如对于 a.x 有一个查找链,从 a.__dict__['x'] 然后是 type(a).__dict__['x'],再继续通过 type(a) 的基类开始。

而如果查找的值是一个描述符对象,则会覆盖这个默认的搜索行为,优先采用描述符的行为,这个行为会因为如果调用而有些不同。这里就只说明例子中的情况。

如果描述符绑定的对象实例,a.x 则转换为调用: type(a).__dict__['x'].__get__(a, type(a))。

当一个描述符之定义 __get__() 方法,则它的绑定关系比一般情况下要弱化很多。特别是,只有当被访问的属性不存在对象字典中时,__get__() 才会被调用。

更多描述可见文档:https://docs.python.org/3/ref...

这种惰性求值的方法在很多模块中都会使用,比如django中的 cached_property:

使用上与例子一致,如表单中的 changed_data :

讨论

在大部分情况下,让属性具有惰性求值能力的全部意义就在于提升程序性能。当不需要这个属性时就能避免进行无意义的计算,同时又能阻止该属性重复进行计算。

本文的技巧中有一个潜在的缺点,就是计算出的值后就变成可变的(mutable)。

>>> c.area

78.53

>>> c.area = 3

>>> c.area

3

如果考虑可变性的问题,可以使用另一种实现方式,但执行效率会稍打折扣:

def lazyproperty(func):

name = '_lazy_' + func.__name__

@property

def lazy(self):

if hasattr(self, name):

return getattr(self, name)

value = func(self)

setattr(self, name, value)

return value

return lazy

如果使用这种方式,就会发现 set 操作是不允许的,所有的 get 操作都必须经由属性的 getter 函数来处理,这比直接在实例字典中查找相应的值要慢一些。

参考

https://docs.python.org/3/ref...

《Python Cookbook 第三版》

python惰性求值_让Python中类的属性具有惰性求值的能力相关推荐

  1. python惰性求值效果_让Python中类的属性具有惰性求值的能力

    起步 我们希望将一个只读的属性定义为 property 属性方法,只有在访问它时才进行计算,但是,又希望把计算出的值缓存起来,不要每次访问它时都重新计算. 解决方案 定义一个惰性属性最有效的方法就是利 ...

  2. 让Python中类的属性具有惰性求值的能力

    起步 我们希望将一个只读的属性定义为 property 属性方法,只有在访问它时才进行计算,但是,又希望把计算出的值缓存起来,不要每次访问它时都重新计算. 解决方案 定义一个惰性属性最有效的方法就是利 ...

  3. python一个函数调用另一个函数的返回值_在python函数中使用True,False和None作为返回值...

    建议不是你不应该使用True,False或None.这只是你不应该使用如果x == True. 如果x == True是愚蠢的,因为==只是一个二进制运算符!它的返回值为True或False,取决于它 ...

  4. python画roc曲线_使用Python画ROC曲线以及AUC值

    AUC介绍 AUC (Area Under Curve)是机器学习二分类模型中非常常用的评估指标,相比于 F1-Score 对项目的不平衡有更大的容忍性,目前常见的机器学习库中(比如 scikit-l ...

  5. python数据框去重_【Python】基于某些列删除数据框中的重复值

    Python按照某些列去重,可用drop_duplicates函数轻松处理.本文致力用简洁的语言介绍该函数. 一.drop_duplicates函数介绍 drop_duplicates函数可以按某列去 ...

  6. python 获取唯一值_从Python列表中获取唯一值

    python 获取唯一值 In this article, we will be understanding 3 ways to get unique values from a Python lis ...

  7. python计算文件md5值_用python计算文件的MD5值

    md5是一种常见不可逆加密算法,使用简单,计算速度快,在很多场景下都会用到,比如:给用户上传的文件命名,数据库中保存的用户密码,下载文件后检验文件是否正确等.下面讲解在python中如何使用md5算法 ...

  8. python怎么检查dataframe 含有none值_关于python:在Pandas DataFrame中用None替换无效值...

    在Python的Pandas中,是否有任何方法可以用None替换值? 您可以使用df.replace('pre', 'post')并将其替换为另一个值,但是如果要替换为None值则无法执行此操作,如果 ...

  9. livechart 只显示 y 值_基于Python语言的SEGY格式地震数据读取与显示编程

    敬请关注<地学新视野> 摘要:本文简单介绍了SEG-Y地震数据文件格式,以及如何用Python语言编写读写SEG-Y格式的地震数据并绘制地震剖面,其中用到了Segyio和matplotli ...

最新文章

  1. 同盾反欺诈云防垃圾灌水帖体验分享
  2. 人均奖金300万,2021年“科学探索奖”名单揭晓:高会军周昆上榜,女性获奖人8位创纪录...
  3. mac 开机执行命令
  4. 关于在pycharm下提示ModuleNotFoundError: No module named 'XXX' 的一种可能
  5. 『设计模式』简单工厂模式
  6. twisted mysql_在Twisted下用MySQLadbapi获取自增id
  7. linux cd是什么目录,linux-cd命令
  8. 即插即用!开源项目【云框架】发布“基于Spring cloud的微服务架构”
  9. 干货:实现数据可视化的几个工具选择(工具+编程语言)
  10. 高性能负载均衡是如何架构的?
  11. 新基建 X 巡检机器人:AI赋能,从“前锋”到“统帅”
  12. Unity 自动寻路入门 NavMeshComponents
  13. 电销机器人源码支持私有云和本地部署
  14. Eclipse+Maven搭建Wbe项目(1)
  15. java短信接口开发完整项目_java项目接入第三方短信接口
  16. Leetcode个人题解714
  17. 视频字幕识别(百度AI开放平台OCR | python | opencv)
  18. Nacos本地进行了远程配置而远程未配置相关信息而导致应用报内存泄漏问题的异常
  19. 分析称诺基亚仅押宝WP成自救牵绊
  20. Android系统之制作开机LOGO

热门文章

  1. 树莓派raspbian OS 64位系统下载和更换源
  2. 【Linux】宝塔Linux面板命令大全
  3. Mac下png转icns图标脚本
  4. 《高性能MySQL》读书笔记-mysql数据类型和应用
  5. 使用python编写自己的进程调试工具
  6. javascript入门_JavaScript入门手册(2020版)
  7. Redux中的功能式React式编程简介
  8. 110_Power Pivot特殊结算日期及财年日期
  9. Spring MVC中的基本流程
  10. python3生成器与迭代器_Python3迭代器与生成器