• 迭代器和生成器


    一、迭代器:iterable(可迭代的,可重复的)

          就是更新重复的过程,每次的迭代都必须基于上一次的结果,内部都是基于for 循环原理

      为什么要用迭代器:迭代器提供了一个不需要按索引取值的方式

    只是简单的重复,没有更新内容这不算是迭代
    
    n = 0
     while True:
         print(n)
    l=[1,2,3,4,5]
    count=0
    while count<len(l):
        print(l[count])
        count+=1
     上述例子就是一个完整的迭代过程

     二、什么是可迭代对象
      可迭代对象指的是内置有__iter__方法的对象,例如:atr 字符串   list 列表  tuple 元组   set 集合    dict  字典 

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

    l2=(1,2,3)
    res=l2.__iter__()
    print(res)
    执行的结果:<tuple_iterator object at 0x000001E48B5BE940>

    l3
    ={'a':1} l3.__iter__() l4={'a','b'} l4.__iter__()
    f=open('03.txt','w',encoding='utf-8')
     f.__iter__()

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

    三、迭代器对象:

      迭代器对象:可以用next获取下一个值(说明实现了next方法),但是每个值只能获取一次,单纯的迭代器没有实现iter魔法函数,所以不能使用for循环

      指的是即内置有__iter__又内置有__next__方法的对象,必须同时满足这两个条件

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

      文件类型是迭代器对象 

    f=open('03.txt','w',encoding='utf-8')
    res1=f.__iter__()
    res2=f.__exit__()
    print(res1,res2)

    1:迭代器的取值调用  __next__

    p=[1,2,3,4,5]
    iter_p=p.__iter__() # 先生成一个迭代器对象,才可以调用
    
    迭代器的取值 调用 ——next——
    print(iter_p._next_())
    # 次数超过容器类型 print(iter_l.__next__()),如果取完了 直接报错

     d = {'name':'gason','password':'123','hobby':'write'}
        # 将可迭代对象d转换成迭代器对象,才可被调用
     iter_d = d.__iter__()
     #迭代器对象的取值 必须用__next__
     print(iter_d.__next__())
     print(iter_d.__next__())
     print(iter_d.__next__())
     print(iter_d.__next__())  # 取完了 报错StopIteration

    打开文件:
    f1=open('03.txt','r',encoding='utf-8')
    iter_f=f1.__iter__()
    print(iter_f is f1)

    注:迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本身

      迭代器取值的特点: 只能依次往后取  不能倒退  取完就会报错

    2、迭代取值的有缺点
        优点:
            1.不依赖于索引取值
            2.内存中永远只占一份空间,不会导致内存溢出
       
        缺点:
            1.不能够获取指定的元素
            2.取完之后会报StopIteration(停止迭代)的错

    四、for 循环的本质:

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

        2:调用了__next__迭代的取值方法

        3:内部有异常捕获StopIteration(停止迭代)超出了范围,,当__next__报这个错,自动结束循环

    l=[1,2,3,4]
    res=map(lambda x:x+1,l)
    print(res.__next__())
    print(res.__next__())
    print(res.__next__())
    print(res.__next__())

    五、生成器:

      人为自定义实现迭代的功能就叫生成器 

    关键字:yield  

    函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行 ,程序中遇到yield会暂停运行等待调入参数 

    def func():
        print('one')
        yield  12   #程序调用函数执行到 yeild 后就会终止
        print('two')
        yield
        print('three')
    res=func()
    print(res.__next__())
    
    结果
    >>>one 
    >>>12
    如果yrilde 后面不传参数的话 返回 None

      利用关键字‘yiled’ 用函数实现 range 原理:

    print(range(1,10))
    
    def my_range(start,end,step=1):
        while start<end:
            yield start
            start+=step
    for j in my_range(1,10):# 循环打印输出1—10
        print(j)

    六、了解:   yield表达式的形成

        利用函数调用的特性和yield的本质在函数中的运用

    def inner(name):
        print('my name is %s'%name)
        while True:
            like=yield  # 如果不传值就结束程序
            print('i like%s'%like)
    def func():
        pass
    res=inner('kevin')
    res.__next__()# 必须先将代码运行至yiled 才能够为其传值
    res1=res.inner('write') # 调用__next_才能执行yiled后面的语句
    print(res)

    yield
        1.帮你提供了一种自定义生成器方式
        2.会帮你将函数的运行状态暂停住
        3.可以返回值

    与return之间的区别
        相同点:都可以返回值,并且都可以返回多个
        不同点:
            yield可以返回多次值,而return只能返回一次函数立即结束
            yield还可以接受外部传入的值

     七、生成器表达式:

        把列表解析的 [] 换成 () 得到的就是生成器表达式

              #生成器表达式 sum(i for i in range(100000000))#几乎不占内存

    res=[i for i in range(1,10) if i!=4]
    print(res)
    #全部打印输出1—10
    
    res1=(i for i in range(1,10000) if i!=4) #生成器表达式
    print(res1)
    # next=res.__iter__() print(res1.__next__())
    print(res1.__next__())
    print(res1.__next__())
    print(res1.__next__())
    # 必须通过触发—next—才会触发

    生成器面试题:

    def demo():
        for i in range(4):
            yield i  # i=[0,1,2,3]  # 遇到—next--才会触发执行 
    
    g=demo()
    
    g1=(i for i in g)  #  for 循环取值赋值给g1,已经取完i中的内存地址
    g2=(i for i in g1)
    
    print(list(g1))
    print(list(g2))
    
    结果:
    >>>[0,1,2,3]
    >>>[]
    def add(n,i):
        return n+i
    def test():
        for i in range(4):
            yield i
    g=test()
    
    for n in [1,10]:
        g=(add(n,i) for i in g)
        # 第一次for循环g=(add(n,i) for i in test())
    
        # 第二次for循环g=(add(n,i) for i in (add(n,i) for i in test()))
    print(n)
    res=list(g)
    
    """
    for i in (add(10,i) for i in test()):  会执行所有的生成器内部的代码
        add(n,i)
    """

    结果输出是:20 21 21 23

    循环执行完第一次 n=10

    八、内置函数: Python中提供了68个内置函数

     常用的内置函数执行:

    1.abs:绝对值

    i=-1.12
    print(abs(i))  #  负数转正

    2.all(全部)  any (部分)

    l = [0,1,0]
     print(all(l))  # 只要有一个为False就返回False
     print(any(l))  # 只要有一个位True就返回True

    3.locals(当地)  美 ['loʊklz]   globals(全球)

    def index():
        username = '我是局部名称空间里面的username'
        print(locals())  # 当前语句在哪个位置 就会返回哪个位置所存储的所有的名字
        #print(globals())  # 无论在哪 查看的都是全局名称空间地址
    index()

    4. bin(二进制)  oct(八进制) hex(十六进制)  int(整形)

    print(bin(10)) # 转换为二进制
     print(oct(10))
     print(hex(10))
    print(int('0b1010',2))  #二进制转换为十进制

    5、布尔值bool  只有两种结果True False       True= 0,空,None

    6、bytes  打印字节数

    7、callable     adj.  可随时支取的,请求即付的,随时可偿还的

    可调用的(可以加括号执行相应功能的)
     l = [1,2,3] def index():     pass print(callable(l)) print(callable(index))

    8、chr  ord   字符的转换

     print(chr(97))  # 将数字转换成ascii码表对应的字符
     print(ord('a'))  # 将字符按照ascii表转成对应的数字

    9、divmod  分页器

    print(divmod(101,10))  # 爬虫

    10、enumerate 枚举

    l = ['a','b']
    for i,j in enumerate(l,1):# 枚举按编号取值 1是初始值,不写默认为0
        print(i,j)
    
    结果:
    >>>1  a
    >>>2   b
    
    应用场景是购物车 按序号选功能

    11、 format 三种玩法:
     {}占位   #格式化输出,和%s %d一样的原理
    {index} 索引 
     {name} 指名道姓  # 字典中用到

    12、type isinstance 判断数据类型

     n = 12
     print(type(n))
    print(isinstance(n,list))  # 判断对象是否属于某个数据类型

    13、pow 幂运算

    print(pow(2,3))   >>> 2**3

    14、help 查看内置原理

    15、print(round(3.4))  把…四舍五入;

    生成器:函数中只要有yield,这个函数就会变成生成器。每次运行到yield的时候,函数会暂停,并且保存当前的运行状态,返回返回当前的数值,并在下一次执行next方法的时候,又从当前位置继续往下走。

  • 相关阅读:
    合并二叉树
    剑指 Offer 68
    剑指 Offer 42. 连续子数组的最大和
    C语言 递归实现迷宫寻路问题
    C语言数据结构 统计英文文字每个“单词”出现次数
    C语言 双链表的频度排序管理
    C语言 插入排序使链表递增
    c语言 简单的天数计算器
    数据结构 链表的头插法逆置
    C语言 删除指定的单词
  • 原文地址:https://www.cnblogs.com/Gaimo/p/11189754.html
Copyright © 2020-2023  润新知