zoukankan      html  css  js  c++  java
  • Python基础—迭代器、生成器(Day13)

    一、迭代器

    1.可迭代对象:遵循可迭代协议,内部含有__iter__方法的对象就叫做可迭代对象。(str、list、tulpe、dict、set)

    查询数据类型的方法

    s = 'laonanhai'
    print(dir(s)) # dir(数据类型)查询数据类型的所有方法
    l1=[1, 2, 3, 4]
    print(dir(l1))
    dic = {'1':'guo'}
    print(dir(dic))
    
    执行输出所有方法

    判断是否是可迭代对象的两种方法:

    1)print('__iter__' in dir(s)) 直接判断__iter__是否在数据类型的方法里。

    2)print(isinstance(l,Iterable))

    from collections import Iterable
    l=[1,2,3,4]
    print(isinstance(l,Iterable))  #True

    2.迭代器:遵循迭代器协议,含有__iter__方法和__next__方法。

    l1=[1,2,3]
    l1_obj = l1.__iter__()
    print('__iter__' in dir(l1_obj)) #True
    print('__next__' in dir(l1))  #False __next__不在可迭代对象中
    print('__next__' in dir(l1_obj)) # True

      可迭代对象转化成迭代器:可迭代对象.__iter__()

    l1=[1,2,3]
    l1_obj = l1.__iter__()
    print(l1_obj.__next__())
    print(l1_obj.__next__())
    print(l1_obj.__next__())
    1
    2
    3
    print一次打印一个元素
    l1_obj = l1.__iter__()
    for i in l1_obj:
        print(i)
    循环打印

    判断是否是迭代器的方法:

    # 方法1
    l1=[1,2,3]
    l1_obj = l1.__iter__()
    print('__iter__' in dir(l1_obj))
    print('__next__' in dir(l1_obj))
    # 方法2
    l1=[1,2,3]
    l1_obj = l1.__iter__()
    from collections import Iterator
    print(isinstance(l1_obj,Iterator))

    迭代器的特点:

    1)节省内存空间。

    2)满足惰性机制。(next一条执行一条)

    3)不能反复取值,不可逆。

    用while循环模拟for循环机制:

    1)将可迭代对象转化为迭代器。

    2)内部使用__next__方法取值。

    3)运用了异常处理去处理报错。

    l1=[1, 2, 3, 4, 5, 6]
    l1_obj=l1.__iter__()
    while True:
        try:
            i=l1_obj.__next__()
            print(i)
        except Exception:
            break

     二、生成器

    自己写的能实现迭代器功能的是生成器,本质上是迭代器,特点是惰性运算。

    生成器的产生方式:

    1.用生成器函数构造。(一条一条打印)

    第一:函数中只要有yield就不是函数,而是一个生成器。

    第二:g称作生成器对象。

    def func1():
        print(111)
        print(222)
        yield 666
        yield 777
    g=func1()
    print(g.__next__())
    print(g.__next__())
    import time
    def genrator_fun1():
        a=1
        print('现在定义了a变量')
        yield a
        b=2
        print('现在定义了b变量')
        yield b
    g1=genrator_fun1()
    print('g1:',g1)
    print('-'*20)
    print(next(g1))
    time.sleep(1)
    print(next(g1))
    def func1():
        for i in range(1,10000):
            yield '老男孩校服%d号'% i
    g = func1()
    for i in range(50):
        g.__next__()
        print(g.__next__())
    for j in range(150):
        print(g.__next__())

    send:send和next功能一样,都是执行一次,send可以给上一个yield赋值,第一次使用生成器时,用next获取下一个值(不能用send),最后一个yield不能接收外部的值。

    def generator():
        print(123)
        content = yield 1
        print(content)
        print(456)
        yield 2 #最后一个yield没有值
    g = generator()
    g.__next__()  #第一个值不能用send
    g.send('hello')
    
    执行结果:
    123
    hello
    456

    2.用生成器推导式。

    1)列表推导式:一行代码搞定,一目了然,占内存,不易排错。

    列表生成式是python内置的非常简单却强大的用来创建list的生成式,例如,要生成list[1,2,3,4,5,6,7,8,9,10]可以用range(1,11)

    x = range(1,11)
    print(x)
    返回结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    单如果要生成[1x1, 2x2, 3x3, ..., 10x10]怎么做呢?

    L = []
    for x in range(1,11)
        L.append(x * x)
    print(L)
    但是循环太繁琐,而列表生成式则可以用一行语句代替循环生成上面的list
    print([x * x for x in range(1,11)])
    执行结果:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
    
    for 循环后面还可以加if判断筛选出仅偶数的平方
    [x * x for x in range(1, 11) if x % 2 == 0]
    
    还可以使用两层循环,生成全排列
    >>>[m + n for m in "ABC" for n in "XYZ"]
    ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

    列表生成式实现九九乘法表

    print("
    ".join(["	".join(["%s*%s=%s"%(j,i,i*j) for j in range(1,i+1)]) for i in range(1,10)]))
    
    1*1=1
    1*2=2    2*2=4
    1*3=3    2*3=6    3*3=9
    1*4=4    2*4=8    3*4=12    4*4=16
    1*5=5    2*5=10    3*5=15    4*5=20    5*5=25
    1*6=6    2*6=12    3*6=18    4*6=24    5*6=30    6*6=36
    1*7=7    2*7=14    3*7=21    4*7=28    5*7=35    6*7=42    7*7=49
    1*8=8    2*8=16    3*8=24    4*8=32    5*8=40    6*8=48    7*8=56    8*8=64
    1*9=9    2*9=18    3*9=27    4*9=36    5*9=45    6*9=54    7*9=63    8*9=72    9*9=81

    2)生成器表达式:通过列表生成式可以创建一个list,但是受到内存的限制列表的容量是有限的,会占用很大的存储空间,如果想要节省内存,提升程序的效率就可以利用生成器generator一边循环一边计算,生成器表达式只要把列表表达式的[ ]改成( )就可以创建一个generator

    g = (x * x for x in range(10))
    print(g)
    执行结果:<generator object <genexpr> at 0x00000000035BC410>
    通过g.__next__()获取generator 的下一个值
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())

    generator保存的是算法,每次调用next()的时候才会计算g的下一个元素值,直到计算到最后一个元素值时,会返回stopIteration的错误。

    3)字典推导式

    mcase = {'a':10,'b':20}
    mcase_frequency = {mcase[k]:k for k in mcase}
    print(mcase_frequency)
    
    执行结果:
    {10: 'a', 20: 'b'}

    4)集合推导式

    squared = list({x**2 for x in [1,-1,2]})
    print(squared)
    
    执行结果:
    [1, 4]

    推导式模式:

    1)循环模式:经过加工的i for i in 可迭代对象。

    l1 = [i*i for i in range(1,11)]
    print(l1)
    
    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

    2)筛选模式:经过加工的i for i in 可迭代对象 if条件筛选。

    l2 = [i for i in range(1,101) if i%3 == 0]
    print(l2)
    
    [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99]
    l3 = [name for i in names for name in i if  name.count('e') == 2 ]
    print(l3)
    
    ['Jefferson', 'Wesley', 'Steven', 'Jennifer']

    3.数据类型的转化

      

  • 相关阅读:
    Android的startActivityForResult()与onActivityResult()与setResult()参数分析,activity带参数的返回
    git stash 保存当前工作状态
    vim diff 的使用
    git pull 命令
    java 开发环境安装
    vim 处理换行符
    git 操作分支
    git 操作远程仓库地址
    vim 宏的使用
    Chrome 调试技巧
  • 原文地址:https://www.cnblogs.com/facestore/p/8711394.html
Copyright © 2011-2022 走看看