美文网首页
使用延迟计算属性

使用延迟计算属性

作者: LittleBear_6c91 | 来源:发表于2019-05-14 20:51 被阅读0次

问题

你想将一个只读属性定义成一个 property,并且只在访问的时候才会计算结果。但是一旦被访问后,你希望结果值被缓存起来,不用每次都去计算。

解决方案

定义一个延迟属性的一种高效方法是通过使用一个描述器类,如下所示:

class lazyproperty:
def __init__(self, func):
self.func = func
def __get__(self, instance, cls):
if instance is None:
return self
else:
value = self.func(instance)
setattr(instance, self.func.__name__, value)
return value

你需要像下面这样在一个类中使用它:

import math
class Circle:
        def __init__(self, radius):
                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.0)
>>> c.radius
4.0
>>> c.area
Computing area
50.26548245743669
>>> c.area
50.26548245743669
>>> c.perimeter
Computing perimeter
25.132741228718345
>>> c.perimeter
25.132741228718345
>>>

仔细观察你会发现消息 Computing area 和 Computing perimeter 仅仅出现一次.
讨论
很多时候,构造一个延迟计算属性的主要目的是为了提升性能。例如,你可以避免
计算这些属性值,除非你真的需要它们。这里演示的方案就是用来实现这样的效果的,
只不过它是通过以非常高效的方式使用描述器的一个精妙特性来达到这种效果的。
正如在其他小节 (如 8.9 小节) 所讲的那样,当一个描述器被放入一个类的定义时,
每次访问属性时它的 get() 、set() 和 delete() 方法就会被触发。不过,
如果一个描述器仅仅只定义了一个 get() 方法的话,它比通常的具有更弱的绑定。
特别地,只有当被访问属性不在实例底层的字典中时 get() 方法才会被触发。
lazyproperty 类利用这一点,使用 get() 方法在实例中存储计算出来的值,
这个实例使用相同的名字作为它的 property。这样一来,结果值被存储在实例字典中并
且以后就不需要再去计算这个 property 了。你可以尝试更深入的例子来观察结果:

>>> c = Circle(4.0)
>>> # Get instance variables
>>> vars(c)
{'radius': 4.0}
>>> # Compute area and observe variables afterward
>>> c.area
Computing area
50.26548245743669
>>> vars(c)
{'area': 50.26548245743669, 'radius': 4.0}
>>> # Notice access doesn't invoke property anymore
>>> c.area
50.26548245743669
>>> # Delete the variable and see property trigger again
>>> del c.area
>>> vars(c)
{'radius': 4.0}
>>> c.area
Computing area
50.26548245743669
>>>

相关文章

  • 使用延迟计算属性

    问题 你想将一个只读属性定义成一个 property,并且只在访问的时候才会计算结果。但是一旦被访问后,你希望结果...

  • iOS中Swift从开始入门到最后的放弃(十3,

    # 延迟计算属性 ####有关延迟计算属性的问题 首先,延迟计算属性本质上就是一个闭包,如果调用的时候这个属性有值...

  • Python 使用延迟计算属性

    很多时候,构造一个延迟计算属性的主要目的是为了提升性能 你想将一个只读属性定义成一个property,并且只在访问...

  • Swift的延迟存储属性

    延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用lazy来标示一个延迟存储属性。延迟属...

  • 属性和方法

    1、属性 存储属性 延迟存储属性 计算属性 只读计算属性 只有 getter 方法但没有 setter 方法的计算...

  • Swift—懒加载

    *延迟存储属性* * 延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用lazy来标示一...

  • iOS开发之Swift篇(9)—— 属性

    目录 版本 存储属性 延迟加载存储属性 计算属性 只读计算属性 属性观察器 类型属性 版本 Xcode 11.3....

  • Swift基础语法-类的属性: 存储属性,延迟存储属性,计算属性

    本节知识点 存储属性 常量存储属性 类和结构体常量与存储属性的关系 延迟存储(懒加载)属性 计算属性 只读计算属性...

  • python: 类属性的延迟计算

    初稿于3.24 延迟计算 所谓延迟,就是将类的某个属性定义成property,这样可以在访问时才进行计算,并且计算...

  • 08-属性

    属性 存储属性 计算属性 注:不能只有set 枚举rawValue原理 延迟存储属性(Lazy Stored Pr...

网友评论

      本文标题:使用延迟计算属性

      本文链接:https://www.haomeiwen.com/subject/dztyaqtx.html