zoukankan      html  css  js  c++  java
  • 面向过程编程-迭代器和生成器

    一:什么是迭代器?

    1.什么是迭代

    迭代是一个重复的过程,并且每次重复都是基于上一次的结果而来的

    while True:
        print(‘------》’)

    没有基于上一次的结果,while这里仅仅是循环
    l=['a','b','c']
    n=0
    while n<len(l):    
        print(l[n])
        n+=1
    每一次的n都是基于上一次n,这里是迭代

    二:什么是迭代器

         要想了解迭代器到底是什么?必须了解一个概念,即什么是可迭代对象。

    可迭代对象,在python中,但凡内置有_iter_方法的对象,都是可迭代对象。

    #以下都是可迭代的对象
    strl='hello'
    listl=[1,2,3]
    tupl=(1,2,3)
    dic={'x':1}
    sl={'a','b','c'}
    f=open('a.txt','w',encoding='utf-8')
    除了数字类型

    三:迭代器

    1.什么是迭代器和举例

    迭代取值的工具,可迭代对象执行_iter_方法得到的返回值就是迭代器对象。

    以上都是可迭代的对象,我们以前学习的都是可以迭代,但是受限于必须有索引。

    而迭代器对象可以避免引用索引,避开这个短处。

    字典:

    dic={'x':1,'y':2,'z':3}
    iter_dic=dic._iter_()
    print(tier_dic._next_())
    print(tier_dic._next_())
    
    电脑输出:
    x
    y
    z

    集合:

    sl={'a','b','c'}
    iter_sl=sl._iter_()
    print(iter_sl._next_())
    print(iter_sl._next_())
    print(iter_sl._next_())
    print(iter_sl._next_())
    print(iter_sl._next_())
    电脑输出:
    b
    a
    c
    print(iter_sl._next_())
    stopiteration
    

    列表:

    list=[1,2,3]
    iter_list=list_iter_()
    print(iter_list.-next-())
    print(iter_list._next_())
    print(iter_list._next_())

    电脑输出:
    1
    2
    3

    字符串:

    l=‘hello’
    iter_l=l._iter_()
    while True:
        print(iter_l._next_())
    电脑输出:
    h
    e
    l
    l
    o
    但执行的时候会报错

    增加抛出异常机制:

    l=[1,2,3,4,5]
    iter_l=l._iter_()
    while True:
        try:
            print(tier_l._next_())
        except StopIteration:
            break

    文件:

    l=open('a.txt','r',encoding='utf-8')iter_l=l._iter_()
    iter_l=l._iter_()

    while True: try: print(iter_l._next_()) except StopIteration: break
    电脑输出:
    11111111

    222222

    333333

    444444

    注意:
    ‘
    ’打印出来了空行 

     2.for循环称之为迭代器循环,in后必须是可迭代对象或者迭代器,因为for要调用系统内置的_iter_方法

    l=open ('a.txt','r',encoding='utf-8')
    for line in l :
        print(line)
    for调用了系统内置方法_iter_

    3.迭代器的优点:

    1.提供了一种可以不依赖索引的取值方法

    2.只生成一个迭代器对象,更加节省内存

    l=open('a.txt','r',encoding='utf-8')
    for line in l:
        print(line)
    电脑输出:
    只是一个内存空间地址而已


      4.迭代器的缺点:

    1.取之麻烦,只能一个一个的next取出来

    2.取值方向只能往后取,而且是一次性使用,无法复用

    x=[1,2,3]
    iter_x=x._iter_()
    while True:
        try:
            print(tier_x._next_())
        except:
            break
    print('第二次====================》‘)
    iter_x=x._iter_().      (必须新建才能复用)
    while True:
        try:
            print(iter_x._next_())
        exceptbreak

    5.可迭代的对象Vs迭代器对象

    可迭代对象(list,str,tuple,dict,set,file)
      1.获取可迭代对象的方式:无需获取,python内置str,list,dict,set,file都是可迭代对象
      2.特点:
        内置_iter_方法的都可以叫做可迭代对象,执行该方法会拿到一个迭代器对象
    迭代对象:
      1.获取迭代器对象的方式,执行可迭代对象的_iter_方法,拿到的返回值就是迭代器对象
      2.内置有_next_方法,执行该方法会拿到迭代器对象的一个值(value)
      3.内置有_iter_方法,执行该方法会拿到迭代器本身(内存地址)

    》》》文件有时候本身较大,占用太多内存,必须定义为一个迭代器对象,节省内存
    四、生成器yield基础
      1.生成器本质就一个迭代器,相当于自己造了一个母鸡。
      生成器的用法其实就是迭代器的用法:
      yield的用法其实就是迭代器的用法:
      yield的用法(针对任何可迭代对象):
        函数内包含yield关键字,在调用函数,就不会执行函数体代码,
        拿到返回值就是一个生成器对象
    def chicken ():
        print('----->first')
        yield 1
        print('------>second')
        yield 2
        print('------->third')
        yield 3
    obj=chicken()
    print(obj)

    电脑输出:(输出的是内存地址)

    <generator object chicken at 0x1031ed150>
    def chicken ():
        print('----->first')
        yield 1
        print('------>second')
        yield 2
        print('------->third')
        yield 3
    obj=chicken()
    res=obj.__next__()
    print(res)
    res1=obj.__next__()
    print(res1)
    res2=obj.__next__()
    print(res2)

    电脑输出:

    ----->first
    1
    ------>second
    2
    ------->third
    3

    2.yield的过程:

      1、iter_obj=obj._iter_(),拿到迭代器

      2、出发iter_obj._next_(),拿到该方式的返回值,赋值给item

      3、周而复始,直到函数内不再有yield,即取之完毕

      4、for会检测到StopIteration异常,结束循环

    for item in obj:

      print(item)

    3、yield的功能

        a》与return类似,都可以返回值,不一样在于,yield可以返回多个值而且可暂停,

          再次执行可继续下一步操作,return到了就停止不在继续执行。

        b》为封装好的函数能够使用_iter_和_next_的方法。

        c》遵循迭代器的取值方式._next_(),触发函数的执行和函数的保存方式都是通过yield保存起来的。

    def foo():
        print('starting')
        while True:
            x=yield
            print('value:  ',x)
    g=foo()
    next(g)    
    # (next(g)==g.send(None))
    g.send(2)
    # send的效果:1、将携带的值传给yield,注意的是yield,而不是x,然后yield赋值给x 2、send()方法和next()方法
    # 一样的功能,也就是继续执行,直到碰到yield结束

    yield表达形式(例如:x=yield)下,生成器会有一个send的操作:

    send的效果:

        1.先从一个暂停位置的那个yield传一个值,然后yield会把值赋值x

        2.与next的功能一样

        3.send传多个值,必须以元组的形式

    def good(func):
        def good1(*args,**kwargs):
            g=func(*args,**kwargs)
            next(g)
            return g
        return good1
    @good
    def eater(name):
        print('%s starting to eat'%name)
        food_list=[]
        while True:
            food=yield food_list
            food_list.append(food)
            print('% start to eat %'%(name,food))
    m=eater('jason')
    m.send('火腿')

    注意点:

    既然send()方法有和next一样的作用,那么我们可不可以这样做:

    def foo():
        while True:
            x=yield
    函数yield,函数执行的结果就是生成器,即foo()就是生成器。而要执行的话就需要next(g)
            print('value',x)
    g=foo()
    g.send(1)
    执行给yield传值,这样行不行呢?

    很显然,是不行的:

    TypeError: can't send non-None value to a just-started generator

    错误提示:不能传递给一个非空值给一个未启动的生成器。

      也就是说,在一个生成器函数未启动之前,是不能传递给数值进去的。必须先传递一个None进去

    或者调用一次next(),才可以进行传值操作。

    4.yield的总结:

      a.为我们提供了一种自定义迭代器的方式,可以再函数内调用yield关键词,调用函数拿到的

      生成器,生成器就是迭代器。

      b.yield可以像是return一样用于返回值

      c.yield可以保存函数的执行状态

    五、生成器yield的表达形式

    def eat(name):
        print('%s ready to eat' %name)
        while True:
            food=yield
            print('%s start to eat %s' %(name,food))
        
    
    dog1=eat('alex')
    dog1._next_()
    dog1._next_()
    dog1.send('骨头')

    电脑输出:

    alex ready to eat
    alex start to eat None
    alex start to eat 骨头

    六:面向过程编程

      1.什么是面向过程

      “过程”是其核心,是解决问题的过程,即先做什么,在做什么。

      2.基于面向过程编程程序,就好比设计一种流水线,类似机械思维方式

      3.总结优缺点:

      优点:复杂的问题流程化,进而简单化

      缺点:可扩展性差,修改流水线的任意一个阶段都会牵一发而动全身。

      应用:扩展性要求不高的场景,典型案例如linux内核,git,http

      4.实例:

      流水线1:

        用户输入用户名、密码——》用户验证——》欢迎界面

      流线线2:

        用户输入sql——》sql解析——》执行功能

        

      





















  • 相关阅读:
    Django学习过程中遇到的问题
    代理工具WebScarab安装(转载)
    MongoDB安装之window版本的安装
    QT打包
    小工具--串口
    多线程--信号量
    关于多线程
    QQ界面及简单操作实现
    udp通信
    char *p = "abc";char p[] = "abc";两者之间的区别
  • 原文地址:https://www.cnblogs.com/wuchenyu/p/8679299.html
Copyright © 2011-2022 走看看