• 迭代器 & 生成器


    迭代器

    # 什么是迭代器    
    	迭代:更新换代的过程,每次迭代都必须基于上一次的结果    
    	迭代器:迭代取值的工具
    
    # 为什么要用:    
    	迭代器提供不依赖于索引取值的方式
    
    # l = [1,2,3,4,5]
    # # 生产一个迭代器对象
    # 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__())      # 如果取完了,直接报错
    

    可迭代对象

    # 可迭代对象   
    	只要内置有__iter__方法的都叫做可迭代对象
    # 基本数据类型中    
    	是可迭代对象的有:        
    	str list tuple dict set         
    	文件对象(执行内置的__iter__之后还是本身 没有任何变化):文件对象本身就是迭代器对象
    ## 补充:
    # 针对双下线开头双下划线结尾的方法,推荐读:双下+方法名
    __iter__()	等价于 iter()
    __len__()	等价于 len()
    __next__()  等价于 next()
    
    # s = [1,2,3,4,5]
    # print(s.__len__())
    # iter(s)
    #
    # res = s.__iter__()   # 等价于 res = iter(s)
    # print(s.__len__())   # 等价于 len(s)
    

    迭代器对象

    # 迭代器对象    
    	1.内置有__iter__方法    
    	2.内置有__next__方法    
    	ps: 迭代器对象一定是可迭代对象    
    	而可迭代对象不一定是迭代器对象    
    	
    # 迭代器取值特点:  
    	优点:
    	1.不依赖与索引取值
    	2.内存中永远只占用一份空间,不会导致内存溢出
    缺点:
    1.不能够获取指定的元素,迭代器只能从头开始
    2.取完之后会报StopIteration错
    
    d = {'name':'jason','password':'123','hobby':'泡m'}
    # # 将可迭代对象d转换成迭代器对象
    iter_d = d.__iter__()
    # # 迭代器对象的取值 必须用__next__
    print(iter_d.__next__())            # name
    print(iter_d.__next__())            # password
    print(iter_d.__next__())            # hobby
    print(iter_d.__next__())            # 当取完了报错:StopIteration
    
    
    # 迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本身
    print(f1 is f1.__iter__().__iter__().__iter__().__iter__())
    f1 = open('xxx.txt','w',encoding='utf-8')
    # # 调用f1的内置的__iter__
    iter_f = f1.__iter__()
    print(iter_f is f1)             # True
    
    
    # 问:__iter__方法就是用来帮我们生成迭代器对象,而文件对象本身就是迭代器对象,为什么还内置__iter__方法?
    
    # 答:为了支持for循环
    

    异常捕获处理

    # 捕获错误异常处理,当使用__next__取值,取完了依然不报错
    d = {'name':'jason','password':'123','hobby':'泡m'}
    iter_d = d.__iter__()
    
    while True:
        try:
             print(iter_d.__next__())
         except StopIteration:						        # 捕获错误StopIteration
             print('捕获到了错误,提醒!!')
             break									# 打印并退出
            
    """
    异常有两大类:
    	1.语法结构错误:需要当场修改 异常捕获没发完成
    	2.逻辑错误:异常捕获可以处理
    """
    

    for循环的内部原理

     d = {'name':'jason','password':'123','hobby':'泡m'}
     for i in d:								# for 循环后面的i关键字 跟着的是一个可迭代对象
         print(i)
    
    
    # for循环内部的本质
        1. 将in后面的对象调用__iter__方法  转换成迭代器对象
        2. 调用__next__ 迭代取值
        3. 内部有异常捕获 StopIteration,当__next__报这个错 自动结束循环
    

    生成器

    生成器:用户自定义的迭代器,本质就是迭代器
    关键字:yield
    
    def func():
         print('first')
         yield 666                       # 函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行
         print('second')
         yield 777			     # yield后面跟的值就是调用迭代器__next__你能得到的值
         print('third')
         yield 888			     # yield既可以返回一个值也可以返回多个值 并且多个值也是按照元组的形式返回
        
    g = func()                           # 生成器初始化:将函数变成迭代器
    print(g.__next__())                  # first 666
    print(g.__next__())                  # second 777
    有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值
    
    
    # 自定义range功能
     for i in range(1,10,2):
         print(i)
     def my_range(start,end,step=1):
         while start < end:
             yield start
            start += step
            
            
    # yield 传值
    # 当函数体代码内有yield关键字时候,调用该函数不会执行函数体代码
     def dog(name):
         print('%s 准备开吃'%name)
         while True:
             food = yield
             print('%s 吃了 %s'%(name,food))
     g = dog('egon')
     g.__next__()         # 必须先将代码运行至yield,才能够为其传值
     g.send('包子')        # 给yield左边的变量传参  触发了__next__方法
    
    # yield
        1. 帮你提供一种自定义生成器的方式 
        2. 保存函数上一次调用状态
        3. 可以返回值
        
    # 与return之间的异同点
        相同:都可以返回值,并且都可以返回多个
        不同点:yield可以返回多次值,而return只能返回一次,函数立即结束
               yield还可以接受外部传入的值
    

    生成器表达式

    # 生成器表达式   
    	生成器不会主动执行任何一行代码    
    	必须通过__next__触发代码的运行
    
    # 案例一:
    res = [i for i in range(1,10) if i != 4]     
    print(res)				               # [1, 2, 3, 5, 6, 7, 8, 9]
    
    # 案例二:
    res = (i for i in range(1,10) if i != 4)
     print(res)                                            # 与案例一不同,取出结果不会直接出现元组,而是生成器
     print(res.__next__())                                 # 取出老母猪,需要一个一个拍
    
    # 案例三:
    with open('xxx.txt','r',encoding='utf-8') as f:        # 将文本中的字符数相加
    	g = (len(line) for line in f)
         print(sum(g))                                     # 相当于是将__next__的结果相加
    

    常用内置方法

    # print(abs(-11.11))              # 绝对值
    # l = [0,1,2]
    # print(all(l))                   # 传过来的元素全部是true就是true,只要有一个为false就返回false
    # print(any(l))                   # 只要有一个true就返回true
    # print(bin(10))                  # 十进制转二进制
    # print(oct(10))                  # 十进制转八进制
    # print(hex(10))                  # 十进制转十六进制
    # print(int('1010',2))            # 二进制转十进制
    # print(bool(1))                  # 布尔值:1为Ture
    # print(bool(0))                  # 布尔值:0为false
    # s = 'hello'
    # print(s.encode('utf-8'))                # 转换成bytes
    # print(bytes(s,encoding='utf-8'))        # 转换成bytes
    
    # 可调用的(可以加括号执行相应功能的)
    # l = [1,2,3]
    # def index():
    #     pass
    # print(callable(l))                # False
    # print(callable(index))            # True
    # print(chr(122))                   # 将数字转换成ascii码表对应的字符
    # print(ord('z'))                   # 将字符按照ascii表转成对应数字
    # dir获取当前名称空间里面的名字
    # l = [1,2,3]
    # print(dir(l))                     # 打印对象中所有支持的名字
    
    # enumerate 枚举
    # l = ['a','b']
    # for i,j in enumerate(l,1):
    #     print(i,j)
    
    s = """
    print('hello baby~')
    a = 1
    b = 2
    print(a + b)
    """
    eval(s)                     # 可执行变量中的代码,但不支持逻辑代码
    exec(s)                     # 支持逻辑代码
    
    # format 三种玩法
    {} 				           # 占位
    {index} 				   # 索引
    {name} 					   # 指名道姓
    
    def name():
         username = '我是局部名称空间的username'
         print(locals())         				 # 查看局部名称空间的变量
    name()
    
    print(globals())           			         # 查看全局变量
    def login():
         """
         一起嗨皮
         :return:
        """
    print(help(login))            				 # 打印注释
    
    n = 1
    print(isinstance(n,int))        	 		 # 判断对象是否属于某个数据类型
    print(pow(10,2))                     		         # 10的2次方
    input().isalpha						 # 不是纯字母返回true,纯字母返回flase
    
  • 相关阅读:
    通过Appium获取iOS应用元素定位的方法
    如何关闭 iPhone的“Automation Running”滚动?
    推荐一款非常牛的二维码生成器
    VNC Viewer 如何复制黏贴文本
    关于远程Mac电脑
    PyCharm 部署与配置 Vue 项目
    Xcode编译失败(build failed) 但是没有报错
    java怎么根据用户设定的时间执行定时任务
    【hyperf2.2】Hyperf框架 基于JsonRpc与Consul的微服务搭建
    Windows Phone 应用之虾米电台
  • 原文地址:https://www.cnblogs.com/tcy1/p/14311674.html
Copyright © 2020-2023  润新知