zoukankan      html  css  js  c++  java
  • 迭代器,生成器

    一、迭代器

    Iterable可迭代的------>__iter__          

    注:只要含有_iter_  方法的都是可迭代的

    [].__iter__  迭代器------>__next__

    注:通过next就可以从迭代器中一个一个获取值 

    总结:

    只要含有__iter__  方法都是可迭代的——>可迭代协议

    内部含有__next__和__iter__ 方法的就是迭代器

    print('__iter__' in dir( [].__iter__()))
    print('__next__' in dir( [].__iter__()))

    迭代器协议和可迭代协议

    1)、可以被for循环的都是可迭代的

    2)、可迭代的内部都有__iter__ 方法

    3)、只要是迭代器,一定可迭代

    4)、可迭代的__iter__ 方法就可以得到一个迭代器

    5)、迭代器中的__next__方法可以一个一个的获取值

    for

    只要是可迭代对象的时候,才能用for

    当我们遇到一个新的变量,不确定能不能for循环的时候,就判断它是否可迭代

    isinstance() 判断列表是不是可迭代的或是迭代器

    迭代器的好处:

    从容器类型中一个一个的取值,会把所有的值都取到

    节省内存空间

               迭代器并不会在内存中再占用一大块内存,而是随着循环,每次生成一个,每次next每次给一个

    def wahaha():
        for i in range(2000000):
            yield '娃哈哈%s'%i
    g = wahaha()
    count = 0
    for i in g:
        count +=1
        print(i)
        if count > 50:
            break
    print('*******',g.__next__())
    for i in g:
        count +=1
        print(i)
        if count > 100:
            break
    View Code

    二、生成器

    本质:迭代器

    迭代器函数:执行之后会得到一个生成器作为返回值

    1)、只要含有yeild关键字的函数都是生成器函数

    2)、yelid不能和return公用且需要写在函数内  

    def generator():
        print(1)
        yield 'a'
        print(2)
        yield 'b'
        yield 'c'
    g = generator()
    # for i in g:
    #     print(i)
    ret = g.__next__()
    print(ret)
    ret = g.__next__()
    print(ret)
    ret = g.__next__()
    print(ret)
    View Code

     生成器的特点:

    1)、调用函数之后函数不执行,返回一个生成器

    2)、每次调用next方法的时候会取到一个值

    3)、直到取完最后一个,再执行next会报错

    从生成器中取值的几个方法:

    1)、next

    2)、for

    3)、数据类型的强制转换:占用内存 

    三、生成器函数的进阶 

     send获取下一个值的效果和next基本一样,只是在获取下一个值的时候,给一个值的位置传递一个数据

    使用send的注意事项

    1)、send作用范围和next一样

    2)、第一次使用生成器的时候,是用next回去下一个值

    3)、最后一个yield不能接受外部的值

    def generator():
        print(123)
        yield 1
        print(456)
        content=yield 2
        print("===",content)
        print(789)
        yield 
    
    g=generator()
    ret=g.__next__()
    print("***",ret)
    ret=g.__next__()
    print("***",ret)
    ret=g.send("hello")
    print("***",ret)
    ret=g.__next__()
    print("***",ret)
    View Code

    生成器的应用

    获取移动平均值

    预激生成器的装饰器

    获取移动平均值

    四、生成器的表达式

    列表推导式格式:
    [每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] #遍历之后挨个处理

    [满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件] #筛选功能

    列表推导式和生成器表达式:
    1)、括号不一样
    2)、返回的值不一样——>几乎不占用内存空间(生成器表达式)

    列表推导式:
    例1、
    30以内所有能被3整除的数
    ret = [i for i in range(30) if i%3 == 0]  #完整的列表推导式
    g = (i for i in range(30) if i%3 == 0)  #完整的生成器推导式
    print(ret)
    View Code

    例2、30以内所有能被3整除的数的平方

    
    
    ret = [i*i for i in (1,2,3,4) if i%3 == 0]
    ret = (i*i for i in range(30) if i%3 == 0)
    print(ret)
    View Code

    例3、找到嵌套列表中名字含有两个‘e’的所有名字

    
    
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    ret=[name for li in names for name in li if name.count("e")==2]
    print(ret)     #['Jefferson', 'Wesley', 'Steven', 'Jennifer']
    View Code
    字典推导式
    例1、将一个字典的key和value对调
    mcase = {'a': 10, 'b': 34}
    ret={mcase[k]:k for k in mcase}
    print(ret)     #{10: 'a', 34: 'b'}
    View Code

    例2、合并大小写对应的value值,将k统一成小写

    mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
    ret={k.lower():mcase.get(k.lower(),0)+mcase.get(k.upper(),0)for k in mcase}
    print(ret)     #{'b': 34, 'a': 17, 'z': 3}
    View Code

    集合推导式,自带去重效果

    squared={i**2 for i in [-1,1,3]}
    print(squared)    #{1, 9}
    View Code
     
     
  • 相关阅读:
    学习笔记9
    学习笔记8
    学习笔记7
    学习笔记6
    学习笔记5
    学习笔记4
    学习笔记3
    学习笔记2
    学习笔记1
    矩形覆盖
  • 原文地址:https://www.cnblogs.com/gaoya666/p/8178886.html
Copyright © 2011-2022 走看看