您的位置:首页 > 编程语言 > Python开发

python generator 的惰性计算

2015-08-26 17:19 579 查看
今天和朋友看到这么一段代码

data = [3, 1, 4, 1, 5,
9, 2, 6, 5, 3,
5, 8, 9, 7, 9,
3, 2, 3, 8, 4]

group_sz = 5

cur_list = []
groups = []

for d in data:
cur_list.append(d)
if len(cur_list) == group_sz:
groups.append(x*x for x in cur_list)
cur_list[:] = []

for g in groups:
square_avg = sum(g) / group_sz
print(square_avg)


这段代码其实就是将数据每5个一组,计算每组的平方平均数。

但是得到的结果却是

0.0
0.0
0.0
0.0
这又是为什么呢?

其实问题就出在了这一句

groups.append(x*x for x in cur_list)


首先要明确一个概念

列表解析:[expr for iter_var in iterable if cond_expr]

生成器表达式:expr for iter_var in iterable if cond_expr

这两个是不同的解析方式,很明显上面的groups使用的是第二种。前者返回一个列表,后者返回一个生成器,处理大数据时,节约内存,效率更高。

生成器表达式使用了“惰性计算”(lazy evaluation,也有翻译为“延迟求值”,call by need,只有在检索时才被赋值( evaluated),所以在列表比较长的情况下使用内存上更有效。

而后面调用了

cur_list[:] = []


这样也就导致了我们结果的输出全部都是0;

如果将groups改为列表赋值

groups.append([x*x for x in cur_list])
即可得到我们想要的答案

当然还有另外的解决方法,就是将

cur_list[:] = []
改为

cur_list = []

这样的话,generator其实绑定的是不同的list,而上面的改变方法,则是将原来的list给清空了。

这里其实就是完全切片拷贝完成了浅拷贝。而后者就是重新分配来一块内存空间。

上述两种修改的方法就有着性能上的抉择了

python虽然简单,但是如果拿来做开发的话,里面很多的性能优化,确实还是得从平时的积累中来啊
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: