zoukankan      html  css  js  c++  java
  • python 迭代器与生成器

    一 迭代器

      可迭代对象:Iterable,例如,ist,str,tuple,dict,set,range(100)。

        具有__iter__方法的叫做可迭代对象。

      迭代器:Iterator,例如,文件句柄。

        具有__next__,__iter__方法的叫做迭代器。

        迭代器调用__iter__()方法还是自身。  

      可迭代对象与迭代器的关系:

        可迭代对象调用了__iter__()方法变成迭代器。

      2 判断是否是可迭代对象,迭代器的方法。

        1 可迭代对象有__iter__方法,没有__next__方法

         迭代器有__iter__ __next__方法

        2 from collections import Iterable/Iteration  

           isinstance()方法

      3 for循环的本质

        for循环可以遍历一个可迭代对象,也可以遍历一个迭代器。

        当遍历一个可迭代对象时,会自动调用其__iter__()方法,变为一个迭代器。然后调用__next__()方法。遇到StopIteration终止。

      4 迭代器取值与索引取值的对照

        迭代器的缺点:不能定点取值。

               不能往回取值。

        迭代器的优点:惰性计算,节省内存。

                 可以遍历字典,集合取值。这点是索引无法做到的。无序且不知道有哪些key值。

    二 生成器 Generator

      生成器本质上是迭代器。  

      生成器是用户写出来的。

      1 生成器的分类

        带有yield关键字的生成器函数

        由生成器表达式生成的生成器 

      2 生成器函数

        带有yield关键字的函数叫做生成器函数。

        与普通函数的不同之处:调用生成器函数返回来是生成器。

        yield关键字:  

          与return相同的部分:

          与rerurn不同的部分:

      

    三 生成器的应用

      生成器可以模仿管道的概念,借助生成器,可以一直往外传值。

      也可以用send方法给生成器传值。

    def foo():
        money=0
        day=0
        average=0
        while True:
            value=yield average
            money+=value
            day+=1
            average=money/day
    g=foo()
    
    print(g.__next__())
    print(g.send(200))

      一些想法:

      想用生成器,首先是要定义函数,函数体内有yield关键字。

      生成器一般与循环配合的使用。

      生成器通过yield向外传值。也可以用send往内传值。

    四    egon课上讲的例子。

      表达式形式的生成器到底有什么用。 拿到生成器,从外边给yield传值。  

      注意:返回来看,send方法调用的必是生成器,send括号内的内容给生成器,拿到生成器后面的返回值。send的作用,传值和__next__()

      进阶一,yiled没有返回值。

    def init(func):
        def wrapper(*args,**kwargs):
            res=func(*args,**kwargs)
            res.send(None)  #等价于next(res),等价于res.__next__()
            return res
        return wrapper
    @init
    def eater(name):
        print('{} ready to eat '.format(name))
        while True:
            food=yield
            print('{} is eating {}'.format(name,food))
    e=eater('alex')
    e.send('dog shit')

      输出:

    alex ready to eat 
    alex is eating dog shit

      进阶二 yield加上返回值。

    def init(func):
        def wrapper(*args,**kwargs):
            res=func(*args,**kwargs)
            res.send(None)  #等价于next(res),等价于res.__next__()
            return res
        return wrapper
    @init
    def eater(name):
        print('{} ready to eat '.format(name))
        food_list=[]
        while True:
            food=yield food_list
            food_list.append(food)
            print('{} is eating {}'.format(name,food))
    e=eater('alex')
    print(e.send('dog shit'))
    print(e.send('cat shit'))

      输出:

    alex ready to eat 
    alex is eating dog shit
    ['dog shit']
    alex is eating cat shit
    ['dog shit', 'cat shit']

      

      进阶三 进阶二中的狗屎,猫屎参数是写死了。可以专门写一个函数,专门make shit。

        分步骤一:

    def make_shit(n):
        for i in range(n):         屎是造出来了,但要传值,给人吃呀
            

        分步骤二:

    def make_shit(people,n):
        for i in range(n):
            people.send('shit{}'.format(i))             加入一个参数,造完shit后,通过send传值people

        分步骤三:

    def init(func):
        def wrapper(*args,**kwargs):
            res=func(*args,**kwargs)
            res.send(None)  #等价于next(res),等价于res.__next__()
            return res
        return wrapper
    @init
    def eater(name):
        print('{} ready to eat '.format(name))
        food_list=[]
        while True:
            food=yield food_list
            food_list.append(food)
            print('{} is eating {}'.format(name,food))
    
    
    
    def make_shit(people,n):
        for i in range(n):
            people.send('shit{}'.format(i))
    e = eater('alex')
    make_shit(e,5)

      输出:

    alex ready to eat 
    alex is eating shit0
    alex is eating shit1
    alex is eating shit2
    alex is eating shit3
    alex is eating shit4

      make_shit 函数造出shit后不断send给people。

      实际上两个函数协同工作的效果。一个函数不断造值,不断发送给另一个函数。 外面的函数给内部的生成器传值。

      进阶四:

      模拟grep 命令。

  • 相关阅读:
    完整java开发中JDBC连接数据库代码和步骤
    2007最后一贴
    ajax数据加载经验分享
    vs2008中文版提供下载(包含中文msdn)
    修改服务器控件的ID和Name
    你使用控件吗?会用吗?
    自定义控件集
    asp.net控件开发基础示例代码打包
    javascript好文章收藏
    wpf学习笔记简单绑定
  • 原文地址:https://www.cnblogs.com/654321cc/p/7473171.html
Copyright © 2011-2022 走看看