我是靠谱客的博主 缓慢柚子,最近开发中收集的这篇文章主要介绍浅谈Python yield使用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

零零碎碎学着python已经好久了,但是总会发现有好些知识点都没学到,今天在牛客网看到了这样一道题:

# 下列代码的运行结果是什么?
def bar(n):
m = n
while True:
m+=1
yield m
b = bar(3)
print b.next()

题目本身没什么难度,所以就不多说了~

emmmm…刚看到题目的时候,果然发现了我印象里没有的东西——yield。迅速查了资料,大概了解到,一般情况下,带有yield的函数不是一般的函数,而是一个生成器(generator)。
yield这个关键字的作用比较类似于return和print,均有输出/返回结果之意,next()表示依次返回迭代结果。

下面,暂且不说generator,先以一个简单的例子——裴波那契数列来说一说yield。

实例1:简单输出裴波那契数列的前n个数。

def fibo(max):
n, a, b = 0, 0, 1
while n < max:
print b
a, b = b, a + b
n = n + 1

这样的写法属于常规操作,但是,函数的可复用性不高。因为fibo()函数没有返回值,其他函数无法获得该函数生成的数列。
这时我们会想到,为了提高函数的可复用性,我们不直接打印出数列,而是去返回一个List.
从而也就得到了下面这种做法。

实例2

def fibo(max):
n, a, b = 0, 0, 1
L = []
while n < max:
L.append(b)
a, b = b, a + b
n = n + 1
return L

通过以上的改动,函数的可复用性大大提高,但是,该函数在运行中占用的内存会随着参数 max 的增大而增大,因此如果要控制内存占用,最好不要用 List来保存中间结果,而是通过 iterable 对象来迭代。

for i in range(1000):
pass
# 会生成一个有1000个元素的List
for i in xrange(1000):
pass
# 不会生成一个 1000 个元素的 List,而是在每次迭代中返回下一个数值,内存空间占用很小。因为 xrange 不返回 List,而是返回一个 iterable 对象。 

利用 iterable 我们可以把 fibo() 函数改写为一个支持 iterable 的 class,这样也就有了下面的实例:

实例3

class Fibo(object):
def __init__(self, max):
self.max = max
self.n, self.a, self.b = 0, 0, 1
def __iter__(self):
return self
# 下一个迭代对象
def next(self):
if self.n < self.max:
r = self.b
self.a, self.b = self.b, self.a + self.b
self.n += 1
return r
raise StopIteration()
for n in Fibo(5):
print n

Fibo 类通过 next() 函数不断返回数列的下一个数,内存占用始终为常数、

然而,

使用 class 改写的这个版本,代码远远没有实例1简洁。如果我们既要保持实例1的简洁性,又要获得 迭代效果,这时,yield 就派上用场了:

实例4

def fab(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1 

这时你就会发现,实例4与实例1的区别仅仅在于将中间的print换成了yield。


因此,简单来说,yield就是把一个普通函数变成了一个生成器。
yield 的好处是显而易见的,把一个函数改写为一个 generator 就获得了迭代能力,比起用类的实例保存状态来计算下一个 next() 的值,不仅代码简洁,而且执行流程异常清晰。

以上大致是今日所得,日后如果遇到相关问题,再对此文另行补充~

最后

以上就是缓慢柚子为你收集整理的浅谈Python yield使用的全部内容,希望文章能够帮你解决浅谈Python yield使用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部