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>(); ...
随机推荐
- Silverlight中获取控件中子控件
如题:,直接来看代码: /// <summary> /// 查找并返回第一个 相同 name的子元素 /// </summary> /// <typeparam name ...
- C语言预处理命令之条件编译(#ifdef,#else,#endif,#if等)
转自:http://www.kuqin.com/language/20090806/66164.html 预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器.可见预处理过程先于编译器 ...
- Entity FrameWork Code First 之Model分离
之前一直用DB First新建类库进行使用,最近开始研究Code First.Code First也可以将Model新建在类库里面,然后通过数据迁移等操作生成数据库. 现在说下主要步骤: 1.新建类库 ...
- ES6数组的扩展--Array.from()和Array.of()
一. Array.from() : 将伪数组对象或可遍历对象转换为真数组 1.何为伪数组 如果一个对象的所有键名都是正整数或零,并且有length属性,那么这个对象就很像数组,语法上称为"类 ...
- MySQL-checkpoint技术
几个知识点: 缓冲池:缓存磁盘数据,通过内存速度弥补CPU速度和磁盘速度的鸿沟. 脏页:LRU列表中被修改的页,和磁盘上的数据不一致 刷新频率:每次有脏页就刷新,开销很大.需要一种刷新机制 数据丢失: ...
- Oracle 数据库比较日期大小
在今天或者今天之前作比较:select * from JN_BUS_KJLWSBJBXX where dqsj < to_date('2007-09-07 00:00:00','yyyy-mm- ...
- centos、linux关机与重启命令详解
Linux centos关机与重启命令详解与实战 Linux centos重启命令: 1.reboot 2.shutdown -r now 立刻重启(root用户使用) 3.shutdown -r 1 ...
- spring security使用哈希加密的密码
之前我们都是使用MD5 Md5PasswordEncoder 或者SHA ShaPasswordEncoder 的哈希算法进行密码加密,在spring security中依然使用只要指定使用自定义加密 ...
- 进程管理工具supervisor
1. 简介 supervisor有两个组件:supervisord和supervisorctl,组成了client/server结构. supervisord负责读入配置文件,然后supervisor ...
- windows远程登录最大连接数