• 2019-07-15 迭代器、生成器、一部分内置函数


    一、迭代器

      什么是迭代:更新换代的过程,每次的迭代都必须基于上一次的结果

      迭代器:迭代取值的工具

      为什么要用迭代器:迭代器给你提供了一种不依赖于索引取值的方式

      1.可迭代对象:内置有__iter__方法的对象,是可迭代对象object.__iter__

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

          str,list,set,dict,tuple

          'hello'.__iter__

          (1,2,3).__iter__       等等  

      2.迭代器对象

        可迭代对象执行object.__iter__()得到的结果就是迭代器对象

        迭代器对象既有__iter__方法又有__next__方法

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

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

        迭代器取值  调用__next__ 

    l = [1,2,3,4]
    l1 = l.__iter__()   #变成迭代器对象了
    
    print(l1.__next__())   #1
    print(l1.__next__())  #2
    print(l1.__next__())  #3
    print(l1.__next__())  #4
    print(l1.__next__())  #取值完了,就会报错
    
    #__next__逐一取值
    

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

        迭代器取值的特点:只能往后依次取,不能后退

        迭代取值:

          优点:

            1.不依赖于索引取值      2.内存中永远只占一份空间,不会导致内存溢出

          缺点:

            1.不能获取指定的元素   2.取完之后会报StopIteration错误

    二、for 循环的本质(重点

      for循环后面的in关键字后面跟的是一个可迭代对象

      for循环内部的本质:(很重要)

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

        2.调用__next__迭代取值

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

    三、生成器

      生成器:就是用户自定义的迭代器,本质是迭代器。

      函数内部加了关键字yield就变成生成器,有yield关键字,那么加括号执行函数的时候不会触发函数体代码运行。yield后面的值需要调用__next__方法你才能获取到,运行到yield时候,运行会暂停。还需要下一个yield后面的值,你就还需要写一个__next__去获取。

      yield既可以返回一个值也可以返回多个值,多个值也是按照元组的形式返回

    def index():
    print('index')
    yield 666
    yield 777,888

    g = index() #生成器初始化:将函数变成迭代器
    print(g.__next__())
    print(g.__next__())

    #结果
    #index
    #666
    #(777,888)

    四、yield表达式形式(支持外界为其传参)   send方法

      当函数内有yield关键字的时候,调用该函数不会执行函数体代码,而是将函数变成生成器。

      用__next__是代码运行到yield暂停下来,返回yield的值,在这里yield没有值,等着我们传入。g.send(),传入的值给左边的变量,并且触发了__next__方法,然后又运行到yield暂停下来。

    def dog(name):
        print('%s 准备开吃'%name)
        while True:
            food = yield
            print('%s 吃了 %s'%(name,food))
    
    g= dog('wee')
    g.__next__()   ## 必须先将代码运行至yield 才能够为其传值
    g.send('狗不理包子')  # 给yield左边的变量传参  触发了__next__方法
    g.send('饺子')
    
    #结果
    wee 准备开吃
    wee 吃了 狗不理包子
    wee 吃了 饺子

      总结:

        yield:

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

          2.会帮你将函数的运行暂停下来

          3.会有返回值

        与return的异同点:

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

          不同点:yield可以返回多次值,return只能返回一次值就结束函数。yield还可以接受外部传入的值

    五、生成器表达式

      生成器代码不会主动执行任何一行代码    必须通过__next__触发代码的运行   

      注意:for 在()里面就是一个生成器表达式,不会触发__next__方法(重点!!!!)

    res = (i for i in range(1,100000000) if i != 4)
    print(res)   #是一个生成器
    print(res.__next__())  #1
    print(res.__next__())  #2

    面试题:生成器的运用

    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在()括号里面,这是一个生成器表达式,n = 1 # 第二次for循环g=(add(n,i) for i in (add(n,i) for i in test())) #这里也是一个生成器表达式,n = 10 print(n) #所以后面的n都是等于10 res=list(g) ---------------------------------------------------------------
    解析:
    n = 10
    解析:第二次for循环
    第一步:放在list中就有__next__方法,可以变成
    g = for i in (add(n,i) for i in test())
        add(n,i)
    第二步:
    然后里面还可以拆开: for i in test() >>> (0,1,2,3)
                  add(n,i) >>>(10,11,12,13)
    第三步: 
    g = for i in (10,11,12,13)
        add(n,i) >>> (20,21,22,23)
    res = list(g) >>> [20,21,22,23]
          
    #最后结果返回的答案是什么
    #A. res=[10,11,12,13]
    #B. res=[11,12,13,14]
    #C. res=[20,21,22,23]  答案
    #D. res=[21,22,23,24]

    六、内置函数

      1. abs()   #求绝对值

    print(abs(-1.11))    #1.11

      2. all()/any()

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

      3.chr()/ord()           应用: 在创建验证码的时候可以用

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

      4.dir()   可以调用当前对象的所有内置方法和魔法方法

    # dir获取当前对象名称空间里面的名字
    l = [1,2,3]
    print(dir(l))

      5.divmod()   应用:可以做分页器

      返回值(商,余数)

    print(divmod(101,10))   #(10, 1)

      6.enumerate()  枚举

    # enumerate 枚举
    l = ['a','b']
    for i,j in enumerate(l,1):  #设置起始值为1,默认为0
        print(i,j) 
    
    # 1 a
    # 2 b

      7.eval()/exec()    把字符串的外面引号去掉,然后运行代码返回结果。注意eval()不支持逻辑代码,只支持简单python代码

    s = """
    print('hello baby~')
    x = 1
    y = 2
    print(x + y)
    
    """
    # eval(s)
    exec(s)
    
    
    #结果
    hello baby~
    3

      8.isinstance()   判断对象是否属于某个数据类型

    n = 1
    print(type(n))
    print(isinstance(n,list))  # 判断对象是否属于某个数据类型   #判断n是否属于list类型
  • 相关阅读:
    7-41 PAT排名汇总 (25分)--排序
    7-40 奥运排行榜 (25分)--sort()排序,结构体,前驱
    7-39 魔法优惠券 (25分)--sort()
    7-38 寻找大富翁 (25分)--sort()
    7-37 模拟EXCEL排序 (25分)--优先队列
    python网络编程--socketserver 和 ftp功能简单说明
    python网络编程--FTP上传文件示例
    python网络编程--粘包解决方案 和 subprocess模块
    python网络编程--socket,网络协议,TCP
    python -- 模块和包
  • 原文地址:https://www.cnblogs.com/wangcuican/p/11192004.html
Copyright © 2020-2023  润新知