• Python笔记(十七):生成器


    (一)生成器(Generator)

    Python生成器是创建迭代器的简单方法。简单来说,生成器是一个函数,它返回一个我们可以迭代的对象(迭代器)(一次一个值)。

    因为下面会用到列表生成式,这里先说明下列表生成式:

    列表生成式:

    theLi = [i*i for i in range(10)]

    下面这段代码的效果和上面的列表生成式是一样的(一开始可能不太习惯列表生成式的写法,多写几次就习惯了):

    L = []
    for i in range(10):
        L.append(i*i)

    可在IDE中将结果打印出来. 

    (二)创建生成器

    1、将列表生成式的[]换成()就行了。

    1 theLi = [i*i for i in range(10)]
    2 
    3 print(theLi)
    4 #创建一个生成器
    5 theGe = (i*i for i in range(10))
    6 
    7 print('生成器:',theGe)

     

    可以看到,print('生成器:',theGe)输出的是一个生成器对象,不会直接输出结果

    2、在函数中定义yield语句就行了(执行到yield语句时,就会返回结果,不过生成器函数和普通函数还是有区别的,下面会说明)

    def theGe():
        i = 1
        yield i
    
    print(type(theGe()))

    (三)生成器函数和普通函数的区别

    1、Generator函数包含一个或多个yield语句。

    2、调用生成器函数时,它返回一个生成器对象,但不会立即执行。

    3、生成器函数会自动实现__iter__()__next__()方法。

    4、执行顺序不同:普通函数执行到最后一句或者return语句时,就返回结果.而生成器函数,则是每次调用next()方法时执行,遇到yied语句就返回结果,再次执行时从上次结束的yield语句处开始执行.(执行顺序的问题,设个断点运行一次就清楚了)。

    5、局部变量和状态会被保存,一直到下一次调用。

    6、函数结束时,抛出StopIteration异常。

    举个例子:

     1 from collections import Iterable
     2 from collections import Iterator
     3 
     4 def gen():
     5 
     6     i = 1
     7     print('第一次:',end='')
     8     yield i
     9     i += 1
    10     print('第二次:',end='')
    11     yield i
    12     i += 1
    13     print('第三次:',end='')
    14     yield i
    15 
    16 print(type(gen()))
    17 #生成器也是迭代器
    18 print(isinstance(gen(),Iterable))
    19 print(isinstance(gen(),Iterator))
    20 
    21 g = gen()
    22 print(next(g))
    23 print(next(g))
    24 print(next(g))
    25 print(next(g))

    (四)生成器的使用

    例如:使用生成器实现杨辉三角

    比较简单的一种理解方式,将每一行都看成一个列表,通过末尾补0的方式来计算下一行列表的值.

    例如:我们知道第二行的元素,我们可以通过下面这种方式获得三行的元素(这个规律是通用的)

     1 #第二行
     2 L2 = [1,1]
     3 
     4 L2.append(0) #此时变成了[1,1,0]
     5 
     6 
     7 L3  = []
     8 # 列表的索引为-1的时候,值=0. L2[-1] = 0
     9 L3.append(L2[-1] + L2[0])
    10 L3.append(L2[0]+L2[1])
    11 L3.append(L2[1]+L2[2])
    12 
    13 print(L3)

    而下面这段代码

    1 L3  = []
    2 # 列表的索引为-1的时候,值=0. L2[-1] = 0
    3 L3.append(L2[-1] + L2[0])
    4 L3.append(L2[0]+L2[1])
    5 L3.append(L2[1]+L2[2])

    其实就是:

    L3  = []
    for i in range(len(L2)):
        L3.append(L2[i-1] + L2[i])

    也是(列表生成式的写法):

    1 L3  = [L2[i-1]+L2[i] for i in range(len(L2))]

    实现杨辉三角:

     1 #杨辉三角
     2 def yhTriangles(n):
     3     yh = [1]
     4     while len(yh) <= n:
     5         yield yh
     6         yh.append(0)
     7         yh = [yh[i-1] + yh[i] for i in range(len(yh))]
     8 
     9 
    10 for i in yhTriangles(10):
    11     print(i)

    (五)使用生成器的优势

    1、易于实现,代码更简洁,容易阅读。(例如:使用迭代器我们需要自己去定义__iter__()和_next_()方法,而生成器会自动处理这些

    2、对内存更加友好.例如:我们创建一个列表的时候,是一创建就存放到内存中的,如果数据量很大,毫无疑问会占用大量内存(而很多时候,我们可能并不需要访问所有数据)。如果列表元素可以通过某种算法推算出来,一边循环一边计算,这样就能节省大量的内存。Python的生成器就可以实现这种功能.

    3、生成器可以代表一个无限的数据流.(无限的数据流是不能直接存放到内存中的,因为内存是有限的)

  • 相关阅读:
    优化不易,且写且珍惜
    作为过来人的感悟:进了小公司的程序员如何翻身进入大公司
    腾讯/阿里/百度 BAT人才体系的职位层级、薪酬、晋升标准
    校招生向京东发起的“攻势”,做到他这样,你,也可以
    通过Java 线程堆栈进行性能瓶颈分析
    基于Spring Cloud的微服务落地
    多线程技术使用指南
    Android 处理含有EditText的Activity虚拟键盘
    Android ListView的监听事件
    Android 开源框架Universal-Image-Loader完全解析(一)--- 基本介绍及使用
  • 原文地址:https://www.cnblogs.com/simple-free/p/9458597.html
Copyright © 2020-2023  润新知