本文转载自微信公众号《暗号》,作者kingname。转载本文请联系Code公众号。粉丝群里有个同学问了这样一个问题:defgen_data(num):ifnum>10:foriinrange(num):yieldielse:returnnumgenerator=gen_data(5)fornumingenerator:print(num)当传入的参数小于等于时到10,为什么没有返回参数本身?对于这道题,当我们传入一个大于10的参数时,可以得到预期的结果,如下图:但是,当我们传入数据5时,我们来看看运行效果:如你所愿看,没有打印数字5,程序直接运行到最后。之所以会出现这种情况,是因为这位同学认为,当参数大于10时,gen_data(12)返回一个生成器,当参数不大于10时,返回一个数字。显然,这种想法是错误的,否则fornumin10的语法早就报错了,numbers无法迭代。正确的说法应该是gen_data(parameter)返回一个generator,因为gen_data中有yield。无论作为参数传入什么,返回的都是一个生成器。如下图:为了解释为什么输入参数为5时for循环不执行,我们简化一下代码:defgen_data():yield1yield2yield3return4generator=gen_data()fornumingenerator:print(num)运行效果如图在下图中:可以看到原来对于这么一个非常简单的生成器,for循环中只打印了数字123,并没有打印数字4。关于generator中的return,我们可以从Python官方文档PEP255—SimpleGenerators[1]中找到解释:returninthegenerator表示generator已经运行完毕,可以结束了。然后生成器抛出StopIteration异常。for循环可以检测到这个异常并结束循环。所以当我们传入的参数为5时,生成器直接运行返回,所以直接抛出StopIteration,所以for循环检测到这个异常就结束了。生成器中的return只是一个结束符,不会将后面写入的值返回给调用者。这与函数中的return语句不同。[1]PEP255—简单生成器:https://www.python.org/dev/peps/pep-0255/#specification-return
