python中计算_Python中的惰性计算

本文中所有代码均运行在Python 2.7上

从迭代器说起

迭代器(Iterator),顾名思义,就是一个可供迭代(Iterables)的对象。

比如,在一个列表中,依次读取其中的元素,就是一个迭代的过程。简单来说,可以使用for ... in ...语句迭代访问的对象,都是迭代器。其中包括list, set, string, dict , file等等。

这种简洁的迭代方式非常简便易用,但同时也带来了一个问题,因为迭代器中所有的数据都被放在内存中以供使用,所以会对内存造成很大的压力。

举个栗子:

>>> for num in range(10**1000):

string = ' ' + ' '

....

OverflowError: range() result has too many items

也许在大多数场景中,我们不会去主动使用range()进行如此大的一个迭代,但我们很有可能会通过open()去打开一个大文件(可能是一个比较大的原始数据文件,或者一个大的log文件等),它的大小很有可能会大于运行环境的内存,这时候程序就会因为OverflowError而崩溃退出。

试试生成器?

同样的,生成器具备迭代器的所有特性,但是它仅供迭代一次,因为它采用的惰性计算的优化策略,就是说它只有当被使用到的时候才把数据取出或者计算出,放到内存中,访问之后随机销毁。

在使用上,它和迭代器的主要区别在于仅能进行一次迭代访问。

>>> iterator = [x for x in range(7)]

>>> Iterator

[0, 1, 2, 3, 4, 5, 6]

>>> generator = (x for x in range(7))

( generator object (genexpr) at 0X00000000025DBA20)

总结

在多数情况下,我们操作的数据量都不足以撼动内存,那是否意味着迭代对我们已经完全够用,生成器完全无用呢?

非也,惰性求值不仅在内存层级对空间有着优化的效果,在计算时间上也有着一定的提高。由于避免了不必要的计算,节省了计算资源。

最后以一个迭代器和生成器之间的斐波那契函数对比结束。

#先来一个迭代版本

def fib(n):

a, b = 0, 1

if n<2:

return [a, b][n]

for i in range():

a, b = b, a+b

return b

#之后是生成器版本

def fibHelper():

a, b = 0, 1

while True:

yield a

a, b = b, a+b

def fib(n):

while n>0:

result = fibHelper()

n -= 1

return result

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值