python之懒惰属性(延迟初始化)
Python 对象的延迟初始化是指,当它第一次被创建时才进行初始化,或者保存第一次创建的结果,然后每次调用的时候直接返回该结果。延迟初始化主要用于提高性能,避免浪费计算,并减少程序的内存需求。
1. 温故下property
property可以将属性的访问转变成方法的调用
class Circle(object):
def __init__(self, radius):
self.radius = radius @property
def area(self):
return 3.14 * self.radius ** c = Circle()
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 ** c = Circle()
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 **
这里与方法1异曲同工,在area()前添加@lazy_property相当于运行以下代码:
lazy_property(area)
lazy_property()方法返回_lazy_property,_lazy_property又会调用_lazy_property()方法,剩下的操作与方法1类似。
#性能差方法
class Circle(object):
def __init__(self, radius):
self.radius = radius @property
def area(self):
print("come in")
return 3.14 * self.radius ** c = Circle()
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 ** c = Circle()
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 ** c = Circle()
print(c.radius)
print(c.area)
print(c.area)
python之懒惰属性(延迟初始化)的更多相关文章
- Python中__get__, __getattr__, __getattribute__的区别及延迟初始化
本节知识点 1.__get__, __getattr__, __getattribute__的区别 2.__getattr__巧妙应用 3.延迟初始化(lazy property) 1.__get__ ...
- Python延迟初始化(lazy property)
转自:https://blog.csdn.net/azsx02/article/details/77649527 Python 对象的延迟初始化是指,当它第一次被创建时才进行初始化,或者保存第一次创建 ...
- Kotlin属性揭秘与延迟初始化特性
在上一次https://www.cnblogs.com/webor2006/p/11210181.html学习了Kotlin的伴生对象,这次来学习属性相关的东东. 属性揭秘: 先声明一个属性: 没啥可 ...
- C#性能优化之Lazy<T> 实现延迟初始化
在.NET4.0中,可以使用Lazy<T> 来实现对象的延迟初始化,从而优化系统的性能.延迟初始化就是将对象的初始化延迟到第一次使用该对象时.延迟初始化是我们在写程序时经常会遇到的情形,例 ...
- C#性能优化:延迟初始化Lazy<T>
1. 概述 我们创建某一个对象需要很大的消耗,而这个对象在运行过程中又不一定用到,为了避免每次运行都创建该对象,这时候延迟初始化(也叫延迟实例化)就出场了. 延迟初始化出现于.NET 4.0,主要用于 ...
- C# 延迟初始化
一个对象的延迟初始化意味着该对象的创建将会延迟至第一次使用该对象时.(在本主题中,术语“延迟初始化”和“延迟实例化”是同义词.)延迟初始化主要用于提高性能,避免浪费计算,并减少程序内存要求. 以下是最 ...
- Lazy<T>延迟初始化
延迟初始化:Lazy<T> 1. 概述 我们创建某一个对象需要很大的消耗,而这个对象在运行过程中又不一定用到,为了避免每次运行都创建该对象,这时候延迟初始化(也叫延迟实例化)就出场了. 延 ...
- Effective Java 第三版——83. 明智谨慎地使用延迟初始化
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- 延迟初始化Lazy
延迟初始化出现于.NET 4.0,主要用于提高性能,避免浪费计算,并减少程序内存要求.也可以称为,按需加载. 基本语法: Lazy<T> xx = new Lazy<T>(); ...
随机推荐
- 《Pro Git》第2章 Git基础
1.获取Git仓库 1.1从现有的目录中初始化仓库 进入项目目录,git init,会创建一个名为.git的子目录 1.2克隆现有的仓库 git clone [url],会将远程Git仓库中的每一个文 ...
- [nowcoder]最长区间
链接:https://www.nowcoder.com/acm/contest/158/B 求最长连续严格递增序列 线段树模板题,码力弱的一匹调了半天.. 代码: #include<iostre ...
- Binder机制-简单用法(一)
Binder算是android里面比较难懂的部分了,但是非常重要,基本上,当我们深入到进程交互的阶段,Binder都是一个绕不开的槛,所以我也希望帮助大家更浅显地了解到这个知识点.笔者想通过3篇博文简 ...
- linux 终端分屏命令
比如:某文件夹下有文件:vector.cc, substr.cc 1.使用vim命令打开任意一个文件:vim vector.cc打开第一个文件.如下图所示: 2.按:"Esc"键 ...
- oracle 子查询详解 in和exists的区别
sql允许多层嵌套,子查询是嵌套在其他查询中的查询.我们可以把子查询当做一张表来看到,即外层语句可以把内嵌的查询结果当做一张表使用. 子查询查询结果有三种情况 不返回查询记录.若子查询不返回记录则主查 ...
- jmeter-执行多个sql查询语句
1.添加jdbc connection(注意标红部分) 2.添加jdbc request 3.查看结果树
- gitlab 卸载
gitlab 卸载 清理命令 sudo gitlab-ctl uninstall sudo gitlab-ctl cleanse sudo gitlab-ctl remove-accounts 停止g ...
- NumPy数学算数函数
NumPy - 算数函数 很容易理解的是,NumPy 包含大量的各种数学运算功能. NumPy 提供标准的三角函数,算术运算的函数,复数处理函数等. 三角函数 NumPy 拥有标准的三角函数,它为弧度 ...
- Treflection04_面试题
1. package reflectionZ; import java.lang.reflect.Field; import java.lang.reflect.Method; public clas ...
- python基础7 - 函数2
4. 使用元组让函数返回多个值 利用 元组 同时返回温度和湿度 def measure(): """返回当前的温度""" temp = 39 ...