yield用法与生成器

参考链接1
参考资料: 《dive into python3》

1 基本用法

1.1 可迭代对象

当你用列表生成式来建立列表时就生成了一个可迭代对象,如下,counter_list就是一个可迭代对象,

counter_list = [x*x for x in range(5)]
for i in counter_list:
    print(i) 

这里所有的值都存在内存当中,所以并不适合大量数据

1.2 生成器(generator)

对此较好的解决方法就是生成器,它具有以下特点:

  • 可迭代

  • 只能读取一次

  • 实时读取数据,不全存在内存中

这样一来生成器的一大好处就是节省内存XD。

1.3 yield关键字

yield是一个类似于return的关键字,但是返回的只是上面所讲的生成器

def make_counter(x):
    print('entering make_counter')
    while True:
        yield x*x
        print('incrementing x')
        x=x+1

counter = make_counter(0)

print(counter) 

如上,最后输出结果如下

<generator object make_counter at 0x108627c50>

1.4 next()函数

next()函数以一个生成器对象为参数,并返回其下一个值。

def make_counter(x):
    print('entering make_counter')
    while True:
        yield x*x
        print('incrementing x')
        x=x+1

counter = make_counter(0)

print(next(counter))

如上,对counter生成器第一次调用next(),它将针对第一条yield语句执行make_counter()中的代码,并返回x*x这个值,并且到此为止,最后输出结果如下

entering make_counter
0

对同一生成器反复调用会从上次开始的位置继续,直到下一条yield语句,如下

def make_counter(x):
    print('entering make_counter')
    while True:
        yield x*x
        print('incrementing x')
        x=x+1

counter = make_counter(0)

print(next(counter))
print(next(counter))

注意是返回到循环语句中开始,相对于只是将循环语句独立出来分步进行,输出结果如下:

entering make_counter
0
incrementing x
1

1.5 for循环输出

for循环能够连续输出,即相当于一直next并输出,注意要设定一个终止条件flag,例如这里的max,如下斐波那契数列:

def fib(max):
    a,b=0,1
    while a < max:
        yield a  # 跟return类似,详见yield用法笔记
        a,b=b,a+b

## 测试
if __name__ == '__main__':
    for n in fib(1000):
        print(n,end=' ')
    print('
')

1.6 list()函数输出

将生成器传给list函数,它将遍历整个生成器(就像上面的for循环)并返回包含所有数值的列表,如下

def fib(max):
    a,b=0,1
    while a < max:
        yield a  # 跟return类似,详见yield用法笔记
        a,b=b,a+b

## 测试
if __name__ == '__main__':
    print(list(fib(1000)))

2 与return的区别

yield用法跟return类似,都会返回值,但是会有以下几点区别

  • return语句象征着函数的结束
def call(i):
    return 2*i
# 从这一行开始不属于函数call部分
    i=i+1
    print(i)
    return 2*i
print(call(4))
原文地址:https://www.cnblogs.com/hzcya1995/p/13281734.html