让属性具有惰性求值的能力

Python-Cookbook每日学习2019-9-13

问题描述

我们定义一个只读属性为property的方法,但此种方法,只有在访问它时才参与计算,如何把所计算的值进行缓存是今天的问题。这样不需要在每次访问时都重新计算。

解决方案

定义一个惰性属性,是快速访问存储值的最佳方案。

class lazyproperty:
    def __init__(self,func):
        self.func=func
    def __get__(self, instance, cls):
        #获取其func参数值
        if instance is None:
            #如果没有获取到参数,则先return到self
            return self
        else:
            value=self.func(instance)
            #如果获取到参数,则计算然后改变其值
            setattr(instance,self.func.__name__,value)
            return value

以上惰性属性,需要使用以下类似代码调用:

class Circle:
    def __init__(self):
        self.radius=radius
    @lazyproperty
    def area(self):
        print ('Computing area')
        return math.pi*self.radius**2
    @lazyproperty
    def perimeter(self):
        print ('Computing perimeter')
        return 2*math.pi*self.radius

思考如下交互式对话如何输出

c=Circle(4)

c.radius
c.area
c.area
c.radius
c.radius

注意此处代码的逻辑,虽然调用两次,但只有一个print,第二次调用使用了缓存值
但是此处需要注意的是,此效率虽然提高了,但是c.area所求出的值是可变的,即可以使用c.area=25来改变相关缓存值,这种操作极不安全。
如果需要防止得出的变量改变,应该需要使用以下效率稍低的方案。
以上操作,属于在底层字典中查询相关的函数值,所以效率极高,但使用如下方式,调用可以不改变其相关的缓存值。

def lazyproperty(func):
    name='lazy_'+func.__name__
    @property
    def lazy(self):
        if hasattr(self,name):
            return getattr(self,name)
        else:
            value=func(self)
            setattr(self,name,value)
            return value
    return lazy

讨论

第二种方法,实现效率稍慢的原因是,每次get操作都需要经过getter函数来处理,所以实现效率不如直接使用__get__魔法函数从python底层字典中查询相关list 或 dir迅速

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值