zoukankan      html  css  js  c++  java
  • Python生成器

    生成器详解

    1.什么是迭代器

    只要定义了__iter__的类那么他就是一个可迭代对象,如果定义了__next__方法那么他就是一个迭代器.

    2.迭代器与生成器的区别

    生成器是一种迭代器,但是迭代器不一定是生成器

    3.什么是生成器

    简单理解为每次生出(yield)一个值的东西

    例子:

    def generator():
        for i in range(3):
            yield i
    

    这个函数就是一个生成器,与普通函数不同的是,当函数执行到yield i语句时,函数会被挂起并且把yield后面的i给返回,当你再次执行该函数时会从yield语句后面接着执行

    不同于return语句的是,return语句不会挂起

    4.生成器的优点

    由于生成器每调用一次就只执行一次,所以生成器占用得到内存就会非常少,看个循环100000000次的例子

    In [185]: def func(): 
         ...:     for i in range(100000000): 
         ...:         pass 
         ...:                                                                                         
    
    In [186]: def gene(): 
         ...:     for i in range(100000000): 
         ...:         yield 
         ...:                                                                                         
    
    In [187]: def getTime(f): 
         ...:     start = time.time() 
         ...:     f() 
         ...:     end = time.time() 
         ...:     print(end-start) 
         ...:                                                                                         
    
    In [188]: getTime(func)                                                                           
    2.0609002113342285
    
    In [189]: getTime(gene)                                                                           
    2.6226043701171875e-06
    
    

    5.生成器的使用

    可以使用next()函数或者__next__()方法来取值,当到最后一个值时会产生异常.

    也可使用for语句取值,并且for语句会自动处理这个异常.

    next()例子:

    In [146]: def generator(): 
         ...:     for i in range(3): 
         ...:         yield i 
         ...:                                                                                         
    
    In [147]: g = generator()                                                                         
    
    In [148]: next(g)                                                                                 
    Out[148]: 0
    
    In [149]: next(g)                                                                                 
    Out[149]: 1
    
    In [150]: next(g)                                                                                 
    Out[150]: 2
    
    In [151]: next(g)                                                                                 
    ---------------------------------------------------------------------------
    StopIteration                             Traceback (most recent call last)
    <ipython-input-151-e734f8aca5ac> in <module>
    ----> 1 next(g)
    
    StopIteration: 
    

    __next__()例子:

    In [146]: def generator(): 
         ...:     for i in range(3): 
         ...:         yield i 
         ...:                                                                                         
    
    In [147]: g = generator()                                                                         
    
    In [148]: next(g)                                                                                 
    Out[148]: 0
    
    In [149]: next(g)                                                                                 
    Out[149]: 1
    
    In [150]: next(g)                                                                                 
    Out[150]: 2
    
    In [151]: next(g)                                                                                 
    ---------------------------------------------------------------------------
    StopIteration                             Traceback (most recent call last)
    <ipython-input-151-e734f8aca5ac> in <module>
    ----> 1 next(g)
    
    StopIteration: 
    

    for例子:

    In [146]: def generator(): 
         ...:     for i in range(3): 
         ...:         yield i 
         ...:                                                                                         
    
    In [147]: g = generator()                                                                         
    
    In [148]: next(g)                                                                                 
    Out[148]: 0
    
    In [149]: next(g)                                                                                 
    Out[149]: 1
    
    In [150]: next(g)                                                                                 
    Out[150]: 2
    
    In [151]: next(g)                                                                                 
    ---------------------------------------------------------------------------
    StopIteration                             Traceback (most recent call last)
    <ipython-input-151-e734f8aca5ac> in <module>
    ----> 1 next(g)
    
    StopIteration: 
    

    注意:不要这样写

    In [162]: def generator(): 
         ...:     for i in range(3): 
         ...:         yield i 
         ...:                                                                                         
    
    In [163]: next(generator())                                                                       
    Out[163]: 0
    
    In [164]: next(generator())                                                                       
    Out[164]: 0
    
    In [165]: next(generator())                                                                       
    Out[165]: 0
    

    直接调用生成器,每次会从头开始,这样就永远只能取到第一个值.(但是for循环可以使用)

    In [162]: def generator(): 
         ...:     for i in range(3): 
         ...:         yield i 
         ...:                                                                                         
    
    In [166]: for i in generator(): 
         ...:     print(i) 
         ...:                                                                                         
    0
    1
    2
    
    

    6.可迭代对象与迭代器

    可迭代对象不一定是迭代器

    str是可迭代对象,但是他不是迭代器:

    	
    In [191]: string = "abcdefg"                                                                      
    
    In [192]: for i in string: 
         ...:     print(i) 
         ...:                                                                                         
    a
    b
    c
    d
    e
    f
    g
    
    In [193]: next(string)                                                                            
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-193-50005732e4cf> in <module>
    ----> 1 next(string)
    
    TypeError: 'str' object is not an iterator
    

    将可迭代对象转换成迭代器:

    In [194]: string = iter(string)                                                                   
    
    In [195]: next(string)                                                                            
    Out[195]: 'a'
    
    In [196]: next(string)                                                                            
    Out[196]: 'b'
    
    In [197]: next(string)                                                                            
    Out[197]: 'c'
    
    

    7.send函数

    使用send函数可以向生成器发送数据,yield左边的变量会接收:

    In [205]: def generator(): 
         ...:     for i in range(10): 
         ...:         recv = yield i 
         ...:         print(recv) 
         ...:                                                                                         
    
    In [206]: g = generator()                                                                         
    
    In [207]: next(g)                                                                                 
    Out[207]: 0
    
    In [208]: next(g)                                                                                 
    None
    Out[208]: 1
    
    In [209]: g.send("hahaha")                                                                        
    hahaha
    Out[209]: 2
    
    In [210]: g.__next__()                                                                            
    None
    Out[210]: 3
    
    In [211]: g.__next__()                                                                            
    None
    Out[211]: 4
    

    对输出结果的解释:

    1. 为什么第一次调用next没有打印东西?

      因为代码在yield语句处挂起,没有执行到print语句

    2. 为什么有些地方得到输出是None

      Noneprint语句的输出结果,输出为None是因为recv变量没有接收到数据

    注意:

    第一次执行就使用send会报错:

    In [213]: def generator(): 
         ...:     for i in range(10): 
         ...:         recv = yield i 
         ...:         print(recv) 
         ...:                                                                                         
    
    In [214]: g = generator()                                                                         
    
    In [215]: g.send("hahahaha")                                                                      
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-215-046ffd60433c> in <module>
    ----> 1 g.send("hahahaha")
    
    TypeError: can't send non-None value to a just-started generator
    

    错误提示为:不能将一个非None的数据传给刚开始的生成器.

    那么就可以这么写

    In [216]: g.send(None)                                                                            
    Out[216]: 0
    

    注意:什么都不写不代表None

    8.协程

    协程是一种多任务(让人感觉同一时间发生了多种事件)的实现方式,生成器可以实现协程

    例:

    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    
    def func1():
        while True:
            yield
            print("----func1被调用----")
    
    
    def func2():
        while True:
            yield
            print("----func2被调用----")
    
    
    def main():
        f1 = func1()
        f2 = func2()
        while True:
            next(f1)
            next(f2)
    
    
    if __name__ == '__main__':
        main()
    

    output:

    ----func1被调用----
    ----func2被调用----
    ----func1被调用----
    ----func2被调用----
    ----func1被调用----
    ----func2被调用----
    ----func1被调用----
    ----func2被调用----
    ----func1被调用----
    ----func2被调用----
    ----func1被调用----
    
    ...
    
    
  • 相关阅读:
    WebRTC学习笔记_Demo收集
    无法获取手机号码
    Hadoop-2.2.0中文文档——Common-Hadoop HTTP web控制台认证
    windows下安装,配置gcc编译器
    Effective C++笔记03:资源管理
    关于打印机状态的获取
    《学习opencv》笔记——矩阵和图像操作——cvInRange,cvInRangeS,cvInvert and cvMahalonobis
    winform Combobox出现System.Data.DataRowView的解决的方法
    CSDN积分规则具体解释--【叶子】
    HTML5中的Web Storage(sessionStorage||localStorage)理解与简单实例
  • 原文地址:https://www.cnblogs.com/kainhuck/p/11113804.html
Copyright © 2011-2022 走看看