python之懒惰属性(延迟初始化)

Python对象的延迟初始化是指,当它第一次被创建时才进行初始化,或者保存第一次创建的结果,然后每次调用的时候直接返回该结果。延迟初始化主要用于提高性能,避免浪费计算,并减少程序的内存需求。1.

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

  Python 对象的延迟初始化是指,当它第一次被创建时才进行初始化,或者保存第一次创建的结果,然后每次调用的时候直接返回该结果。延迟初始化主要用于提高性能,避免浪费计算,并减少程序的内存需求。

1. 温故下property

  property可以将属性的访问转变成方法的调用

class Circle(object): 
  def __init__(self, radius): 
    self.radius = radius 
  
  @property
  def area(self): 
    return 3.14 * self.radius ** 2
  
c = Circle(4) 
print c.radius 
print c.area 

  可以看到,area虽然是定义成一个方法的形式,但是加上@property后,可以直接执行c.area,当成属性访问。

  现在问题来了,每次调用c.area,都会计算一次,太浪费cpu了,怎样才能只计算一次呢?这就是lazy property

2.lazy property实现

  实现延迟初始化有两种方式,一种是使用python描述符,另一种是使用@property修饰符

方法1:

class lazy(object): 
  def __init__(self, func): 
    self.func = func 
  
  def __get__(self, instance, cls): 
    val = self.func(instance) 
    setattr(instance, self.func.__name__, val) 
    return val 
  
class Circle(object): 
  def __init__(self, radius): 
    self.radius = radius 
  
  @ lazy
  def area(self): 
    print 'evalute'
    return 3.14 * self.radius ** 2
  
c = Circle(4) 
print c.radius 
print c.area 
print c.area 
print c.area 

   结果'evalute'只输出了一次。在lazy类中,我们定义了__get__()方法,所以它是一个描述符。当我们第一次执行c.area时,python解释器会先从c.__dict__中进行查找,没有找到,就从Circle.__dict__中进行查找,这时因为area被定义为描述符,所以调用__get__方法。

  在__get__()方法中,调用实例的area()方法计算出结果,并动态给实例添加一个同名属性area,然后将计算出的值赋予给它,相当于设置c.__dict__['area']=val

当我们再次调用c.area时,直接从c.__dict__中进行查找,这时就会直接返回之前计算好的值了。

方法2:

def lazy_property(func):
    attr_name = "_lazy_" + func.__name__
 
    @property
    def _lazy_property(self):
        if not hasattr(self, attr_name):
            setattr(self, attr_name, func(self))
        return getattr(self, attr_name)
 
    return _lazy_property
 
class Circle(object): 
  def __init__(self, radius): 
    self.radius = radius 
  
  @lazy_property
  def area(self): 
    print 'evalute'
    return 3.14 * self.radius ** 2

   这里与方法1异曲同工,在area()前添加@lazy_property相当于运行以下代码:

lazy_property(area)

  lazy_property()方法返回_lazy_property_lazy_property又会调用_lazy_property()方法,剩下的操作与方法1类似。

python之懒惰属性(延迟初始化)
python之懒惰属性(延迟初始化)

#性能差方法
class Circle(object): 
    def __init__(self, radius): 
        self.radius = radius 

    @property
    def area(self): 
        print("come in")
        return 3.14 * self.radius ** 2
  
c = Circle(4) 
print(c.radius) 
print(c.area) 
print(c.area) 

#方法1
class LazyProperty:
    def __init__(self, method):
        self.method = method
        
    def __get__(self, instance, cls):
        if not instance:
            return None
        value = self.method(instance)
        setattr(instance,self.method.__name__,value)
        return value
        
class Circle(object): 
    def __init__(self, radius): 
        self.radius = radius 

    @LazyProperty
    def area(self): 
        print("come in")
        return 3.14 * self.radius ** 2
        
c = Circle(4) 
print(c.radius) 
print(c.area) 
print(c.area)

#方法2
def LazyProperty(func):
    attr_name = "_lazy_" + func.__name__
 
    @property
    def wrap(self):
        if not hasattr(self, attr_name):
            setattr(self, attr_name, func(self))
        return getattr(self, attr_name)
    return wrap
    
class Circle(object): 
    def __init__(self, radius): 
        self.radius = radius 

    @LazyProperty
    def area(self): 
        print("come in")
        return 3.14 * self.radius ** 2
        
c = Circle(4) 
print(c.radius) 
print(c.area) 
print(c.area)

View Code

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120056.html原文链接:https://javaforall.net

(0)
上一篇 2021年12月29日 下午6:00
下一篇 2021年12月29日 下午7:00


相关推荐

  • 【保姆级教程】DeepSeek 接入 MCP 超详细步骤!10 分钟搞定

    【保姆级教程】DeepSeek 接入 MCP 超详细步骤!10 分钟搞定

    2026年3月16日
    3
  • Vue 实例

    Vue 实例创建一个 Vue 实例每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的 varvm newVue 选项 虽然没有完全遵循 MVVM 模型 但是 Vue 的设计也受到了它的启发 因此在文档中经常会使用 vm ViewModel 的缩写 这个变量名表示 Vue 实例 当创建一个 Vue 实例时 你可以传入一个选项对象 这篇教程主要描述的就是如何使用这些选项来创建你想要的行为 作为参考 你也可以在 API 文档中浏览完整的选项列表

    2026年3月18日
    2
  • android游戏开发引擎_android主题引擎

    android游戏开发引擎_android主题引擎随着Android系统的使用越来越广泛,了解一下Android平台下的游戏引擎就非常有必要。而同时因为基于Intelx86的移动设备越来越多,我也非常关注支持x86的移动游戏引擎。然而就目前为止游戏引擎的数量已经非常之多,每个引擎都有不同的特征、价格、成熟度等。通过一些调研之后,我发现有非常多的游戏引擎可用于开发运行在android移动设备端的游戏,其中有些还支持x86系统,另外还有些通过简单的

    2025年8月15日
    4
  • pycharm注释的快捷键_pycharm注释比较多怎么办

    pycharm注释的快捷键_pycharm注释比较多怎么办用鼠标选中需要注释的代码,三次按下:shift+‘即可快速注释

    2022年8月28日
    5
  • 数据结构顺序表基本操作(C/C++实现)

    数据结构顺序表基本操作(C/C++实现)数据结构顺序表基本操作 C C 实现 涉及基本运算初始化顺序表 L 依次插入 abcde 元素输出顺序表 L 输出顺序表 L 的长度判断顺序表 L 是否为空输出顺序表 L 的第 3 个元素输出元素 a 的位置在第 4 个元素位置上插入 f 元素输出顺序表 L 删除顺序表 L 的第 3 个元素输出顺序表 L 释放顺序表 LGitHub 地址 包含 cpp 文件和可执行程序 exe 我的数据结构 GitHub 地址源代码 经 VS2

    2026年3月18日
    2
  • java velocity 语法_Velocity 语法

    java velocity 语法_Velocity 语法VelocityNotes变量名$name为空时打印变量本身。$!name为空时打印空字符串(不打印任何内容)。${name}类似$name,为空时原样打印。但可以将变量和连续的字符串分隔,例如:${name}space。$!{name}类似$!name,为空时打印空字符串,但可以将变量和连续的字符串分隔。例如:$!{name}space。$name$!name${name}$!{name…

    2022年7月14日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号