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

    迭代器

    什么是迭代器?

      迭代:更新换代(重复)的过程,每次的迭代都必须基于上一次的结果

      迭代器:迭代取值的工具

    为什么要用?

      迭代器给你提供了一种不依赖与索引取值的方式

    n = 0
    while True:
        print(n)
    #这就是不算是迭代器,只是简单的重复
    
    l = [1,2,3,4]
    s = 'hello'
    n = 0
    while n < len(s):
        print(n)
        n+=1
    #重复+每次迭代都是基于上一次的结果而来的

    需要迭代取值的数据类型:

      字符串

      列表

      元组

      字典

      集合

    可迭代对象:只要内置有__iter__方法的都叫做可迭代对象

    基本数据类型中是可迭代的对象有:

      str    list    tuple  set   dict

      文件对象(执行内置的__iter__之后还是本身   没有任何变化):文件对象本身就是迭代器对象

    s = 'hello'
    l = [1,2,34,]
    t = (1,2,34)
    s1 = {1,2,3,4}
    d = {'name':'jason'}
    f1 = open('xxx.txt','w',encoding='utf-8')
    
    res = s.__iter__()  # res = iter(s)
    print(s.__len__())  # 简化成了len(s)
    res1 = l.__iter__()  # res1 = iter(l)
    res2 = f1.__iter__()  # res2 = iter(f1)
    print(res,res1,res2)
    print(f1)

    可迭代对象执行内置的__iter__方法得到就是该对象的迭代器对象

    迭代器的取值

    迭代器对象:

      1.内置有__iter__方法

      2.内置有__next__方法

      ps:迭代器一定是可迭代对象,而可迭代对象不一定是迭代器对象

    l = [1,2,3,4]
    iter_l = l.__iter__() #生成一个迭代器对象
    
    #迭代器取值调用__next__
    print(iter_l.__next__())
    print(iter_l.__next__())
    print(iter_l.__next__())
    print(iter_l.__next__())
    print(iter_l.__next__())  #如果取完了  直接报错
    
    d = {'name':'yzy','sex':'male'}
    #将可迭代对象d转换成迭代器对象
    iter_d = d.__iter__()
    #迭代器对象的取值必须用__next__
    print(iter_d.__next__())
    print(iter_d.__next__())
    print(iter_d.__next__()) #取完了  报错StopIteration

    迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本事(******)

    d = {'name':'jason','password':'123','hobby':'泡m'}
    iter_d = d.__iter__()
    
    #异常处理
    while True:
        try:
            print(iter.d__next__())
        except StopIteration:
            print('no')
            break
    d = {'name':'jason','password':'123','hobby':'泡m'}
    iter_d = d.__iter__()
    
    #异常处理
    while True:
        try:
            print(iter.d__next__())
        except StopIteration:
            print('no')
            break

    迭代器取值的特点:

      只能往后依次取,不能后退

    Ps:可迭代对象执行内置的__iter__方法得到的就是该对象的迭代器对象

    d = {'name':'jason','password':'123','hobby':'泡m'}
    for i  in d:
        print(i)
    #for循坏后面的in关键  跟的是一个可迭代对象
    

     for循坏内部的本质

      1.将in后面的对象调用__iter__转换成迭代器对象

      2.调用__next__迭代取值

      3.内部有异常捕获StopIteration,当__next__报这个错  自动结束循坏

    可迭代对象:内置有__iter__方法

    迭代器对象:既内置有__iter__也有内置__next__方法

    迭代取值:

      优点:

        1.不依赖与索引取值

        2.内存中永远只占一份空间,不会导致内存溢出

      缺点:

        1.不能够获取指定的元素

        2.取完之后会报StopIteration错

    生成器

      用户自定义的迭代器,本质上就是迭代器

     def func():
         print('first')
         yield  666  # 函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行
         print('second')
         yield  777
         print('third')
         yield  888
         print('forth')
         yield
         yield
    
    #yield 后面跟的值就是调用迭代器__next__方法你能得到的值
    #yield既可以返回一个值也可以返回多个值,并且多个值也是按照元组的形式返回
    g = func()#生成器初始化:将函数变成迭代器
    print(g)
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    

    #yield支持外界为其传参

    def dog(name):
        print('%s 准备开吃'%name)
        while True:
            food = yield
            print('%s 吃了 %s'%(name,food))
    当函数内有yield关键字的时候,调用该函数不会执行函数体代码
    而是将函数变成生成器
    g = dog('yyy')
    g.__next__()  # 必须先将代码运行至yield 才能够为其传值
    g.send('apple')  # 给yield左边的变量传参  触发了__next__方法
    

    yield

      1.帮你提供了一种自定义生成器方式

      2.会帮你将函数的运行状态暂停

      3.可以返回值

    与return之间的异同点:

      相同点:都可以返回值,都可以返回多个

      不同点:

        yield可以返回多次值,而return只能返回一次函数立即结束

        yield还可以接受外部传入的值

    生成器表达式

    res = (i for i in range(1,100) if i != 4)  #生成器表达式
    
    #生成器不会主动执行任何一行代码,必须通过__next__触发代码的运行
    print(res.__next__())
    print(res.__next__())
    print(res.__next__())
    print(res.__next__())
    with open('name.txt','r',encoding='utf-8')as f:
        n = 0 
        for line in f:
            n += len(line)
        print(n)
    
    
    g = (len(line) for line in f)
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    print(sum(g))

    常用的内置方法

    abs()#求绝对值

    abs(-1)

    print(bin(10))  #2进制
    print(oct(10))   #8进制
    print(hex(10))   #16进制 
    print(int('0b1010',2)    #将2进制转换成10进制
    
    callable()#判断是否可调用
    
    print(chr(97))#将数字转换成ascii码表对应的字符
    print(ord('a')) #将字符按照ascii表转成对应的数字
    
    dir 获取当前对象名称空间里面的名字
    l = [1,2,3]
    print(dir(l))
    
    divmod  分页器
    print(divmod(100,10))
    
    total_num,more = divmod(900,11)
    if more:
        total_num += 1
    print('总页数:',total_num)
    
    enumerate 枚举
    l = ['a','b']
    for i,j in enumerate(l,1):
        print(i,j)
    
    eval exec
    s = """
    print('hello baby')
    x = 1
    y = 2
    print(x+y)
    """
    eval(s)
    exec(s)
    #eval 不支持逻辑代码,只支持一些简单的python代码
    
    isinstance  判断对象是否属于某个数据类型
    n = 1
    print(inistance(n,int))
    
    pow
    print(pow(2,3))  #8
    
    round
    print(round(3.4))   # 3
    print(round(3.6))    #4

    面向过程编程:就类似与设计一条流水线

      好处:

        将复杂的问题流程化  从而简单化

      坏处:

        可扩展性较差  一旦需要修改   整体都会受到影响

  • 相关阅读:
    10 个深恶痛绝的 Java 异常。。
    为什么公司宁愿 25K 重新招人,也不给你加到 20K?原因太现实……
    推荐一款代码神器,代码量至少省一半!
    Spring Cloud Greenwich 正式发布,Hystrix 即将寿终正寝。。
    hdu 3853 LOOPS(概率 dp 期望)
    hdu 5245 Joyful(期望的计算,好题)
    hdu 4336 Card Collector(期望 dp 状态压缩)
    hdu 4405 Aeroplane chess(概率+dp)
    hdu 5036 Explosion(概率期望+bitset)
    hdu 5033 Building (单调栈 或 暴力枚举 )
  • 原文地址:https://www.cnblogs.com/KrisYzy/p/11190156.html
Copyright © 2011-2022 走看看