生成器

自作多情 提交于 2020-02-01 14:56:33

为什么需要生成器

假如要输入1-1亿的数字, 我们采用range的方式生成数据, 那么程序就会崩溃
采用生成器的方式可以解决这个问题, 生成器不会一次把所有的数据加载到内存中, 而是在循环时临时生成的, 循环一次生成一次, 所以程序运行期间永远只能生成一个数据, 从而大大的节省了内存

解决输入1-1亿数字的问题

  • 生成器使用'()'格式
  • 调用__next__方法,依次输入生成器中的一个数据
list_num = (i for i in range(1, 100000000))
print(type(list_num))  # class 'generator'
print(list_num.__next__())
for i in list_num:
    print(i)

next函数和__next__方法:

  • next函数next函数和__next__方法可以迭代生成器的返回值
list_num = (i for i in range(1, 100000000))
print(type(list_num))  # class 'generator'
print(list_num.__next__())

yield表达式

  • 生成器可以通过函数产生, 如果在一个函数中出现了yield表达式, 那么这个函数不再是普通的函数, 而是一个生成器函数

  • yield函数一次返回一个结果, 并且会冻结当前函数的状态
    在这里插入图片描述

  • 例子2: 使用函数式编程实现输出1-1亿的数字

def my_gen(start, end):
    index = start
    while index <= end:
        yield index
        index += 1


res = my_gen(1, 1000000)
for i in res:
    print(i)

send方法

  • send方法和next方法类似, 可以触发生成器的下一个yield, 但是send还可以发送数据作为yield的值
  • 在这里插入图片描述
  • send方法第一次触发发送的值必须是None
    在这里插入图片描述
  • send方法和next方法的区别
  • send方法可以传递值给yield表达式, 而next不可以
  • 在第一次执行生成器代码时, send函数必须要传一个None进去

生成器异常StopIterator

  • 如果生成器中值被取完了会抛出异常
  • 如果出现了return语句也会触发异常
list_num = (i for i in range(1, 2))
print(type(list_num))  # class 'generator'
print(list_num.__next__())
try:
    print(list_num.__next__())
except StopIteration:
    print('quit')

生成器小案例

  • 斐波拉契算法

#  0 1 1 2 3 5 8
def fib(count):
    """
    :param count: 需要生成多少个数字
    :return:
    """
    index = 0
    a = 0
    b = 1
    print(a)
    while index < count:
        print(b)
        c = b
        b = a + b
        a = c
        index += 1


fib(10)
  • 使用yield优化

在这里插入图片描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!