Python生成器你所不知道的

用Python写迭代器(Iterator)的时候,可能会有人向你推荐生成器(Generator),并列举一堆生成器的好处。不过,今天要来分享一个生成器的坑……

很多人学习python,不知道从何学起。

很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。

很多已经做案例的人,却不知道如何去学习更加高深的知识。

那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!??¤

QQ群:1057034340

假如我们要来写一个归一化函数,简单看个例子:

def normalize(numbers):
 total = sum(numbers)
 result = []
 for v in numbers:
 p = 100.0 * v / total
 result.append(p)
 return result
 
 
def main():
 data = [12, 20, 35, 9]
 print normalize(data)

正常情况下输出结果非常符合预期:

[15.789473684210526, 26.31578947368421, 46.05263157894737, 11.842105263157896]

但……

如果 numbers 传入了一个generator,那结果会变成什么样子呢?我们来试一下:

def gen_data(data):
 for v in data:
 yield v
 
def main():
 data = [12, 20, 35, 9]
 gen = gen_data(data)
 print normalize(gen)

猜猜结果输出什么:

[ ]

没错,是空列表!怎么回事呢?是for循环里的生成器坏了,试试直接输出:

def main():
 data = [12, 20, 35, 9]
 gen = gen_data(data)
 for v in gen:
 print v

输出结果:

没问题呀!

那……

排除生成器本身的问题,那肯定是normalize函数错了。断点看一下:

def normalize(numbers):
 total = sum(numbers)                  -------> 这里没错,total=76
 result = []
 for v in numbers:                     -------> for循环竟然直接跳过了
 p = 100.0 * v / total
 result.append(p)
 return result

仔细想想,生成器的原理是什么?调用next() 获取下一个元素的值,直到返回 StopIteration。

这样子就说得通了,sum() 把生成器遍历了一遍,等到for循环的时候,已经没有内容需要遍历了。

def main():
 data = [12, 20, 35, 9]
 gen = gen_data(data)
 t1 = sum(gen)
 t2 = sum(gen)
 print t1, t2

结果输出:

改……

这里提供一个简单的解决方法:

class GenData(object):
 def __init__(self, data):
 self.data = data
 
 def __iter__(self):
 for v in self.data:
 yield v

至于为啥,留给你思考一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值