Python3 学习笔记17_高级特性(生成器)_20180307

本文介绍Python中的生成器概念,包括其基本用法、如何通过列表生成式创建生成器及使用函数定义复杂逻辑的生成器。此外,还探讨了生成器的工作原理及如何正确处理生成器的返回值。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 学习网站:www.liaoxuefeng.com

#****************************************************
#                   Python3 高级特性-生成器         *
#****************************************************
print ("--------------------分割线------------------")

#============
# 生成器
#============
'''
通过列表生成式,可以直接创建一个列表。但受内存限制,列表容量有限,而且
创建百万级元素的列表,不仅占用存储空间,如果只访问前几个元素,后面
元素占用的空间会白白浪费。

列表元素可以按照某种算法推算出来,在循环的过程中不断推算出后续的元素
这样就不必创建完整的list,节省大量的空间,这种一边循环一边计算的机制
称为生成器:generator。
'''

# 创建generator方法一:把列表生成式的[]改成()
list_a = [x*x for x in range(5)]
print( list_a )                     # [0, 1, 4, 9, 16]

gen_a = (x*x for x in range(5))
print( gen_a ) 
# <generator object <genexpr> at 0x000002174EE158E0>

# 通过next()函数获得generator的下一个返回值,每次调用next(gen_a),就
# 计算出gen_a的下一个元素的值,直到最后一个值,没有更多元素则抛出
# StopIteration的错误

print( next(gen_a),next(gen_a) )    # 0 1

# 通常使用for循环获取generator元素
gen_b = (x*x for x in range(5))
for n in gen_b:
    print(n, end=' ')               # 0 1 4 9 16
print()
print ("--------------------分割线------------------")

# 如推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候
# 还可以用函数来实现。

# 例:普通函数斐波那契数列  1, 1, 2, 3, 5, 8, 13,...
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print( b,end=' ' )
        a, b = b, a+b
        n = n + 1
    return 'done'

print( fib(7) )                     # 1 1 2 3 5 8 13 done

# fib函数实际上定义了斐波那契数列的推算规则,把fib函数变成generator
# 只需要把print(b)改为yield b,这也是定义generator的另一种方法。

# 重新定义fib1函数,变为generator
def fib1(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a+b
        n = n + 1
    return 'done'

print( fib1(5) )
# <generator object fib1 at 0x0000014483FB5990>

aa = fib1(3)
print( next(aa),next(aa),next(aa) )     # 1 1 2 
'''
generator与函数的执行流程不一样。函数是顺序执行,遇到return语句或者
最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候
执行,遇到yield语句返回,再次执行时,从上次返回的yield语句处继续执行。
'''

'''
在fib1循环过程中,必须要给循环设置一个条件退出循环,例如n<max,不然
就会产生一个无限数列出来。
函数变为generator后,基本不会用next()来获取下一个返回值,而是直接使用
for循环来迭代。
'''
for n in fib1(3):
    print(n, end=' ')                   # 1 1 2 
print()
print ("--------------------分割线------------------")

'''
上面for循环调用generator时,发现拿不到generator的return语句的返回值
如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在
StopIteration的value中。
'''
gen_c = fib1(5)
while True:
    try:
        x = next(gen_c)
        print('gen_c',x)
    except StopIteration as e:
        print('Generator return value:', e.value)
        break

'''
执行结果:
gen_c 1
gen_c 1
gen_c 2
gen_c 3
gen_c 5
Generator return value: done
'''

'''
小结:
可以简单地把列表生成式改成generator,也可以通过函数实现复杂逻辑的generator

generator工作原理:它是在for循环的过程中不断计算出下一个元素,并在适当
的条件结束for循环。对于函数改成的generator来说,遇到return语句或这执行到
函数体最后一行语句,就是结束generator的指令,for循环随之结束。
'''


# 杨辉三角:
def triangles(max):
    list_x = [1]
    y = 1
    while y < max :
        yield list_x
        list_x = [1] + [ list_x[n] + list_x[n+1] for n in \
        range(len(list_x)-1) ] + [1]
        y = y + 1

for n in triangles(8):
    print( n )

'''
执行结果:
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
'''
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值