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被调用----
    
    ...
    
    
  • 相关阅读:
    Hdu 1257 最少拦截系统
    Hdu 1404 Digital Deletions
    Hdu 1079 Calendar Game
    Hdu 1158 Employment Planning(DP)
    Hdu 1116 Play on Words
    Hdu 1258 Sum It Up
    Hdu 1175 连连看(DFS)
    Hdu 3635 Dragon Balls (并查集)
    Hdu 1829 A Bug's Life
    Hdu 1181 变形课
  • 原文地址:https://www.cnblogs.com/kainhuck/p/11113804.html
Copyright © 2011-2022 走看看