zoukankan      html  css  js  c++  java
  • python笔记之迭代器和生成器

    生成器

    生成器函数 —— 本质上就是我们自己写得函数

    def generator():
        print(1)
        return 'a'
    
    ret = generator()
    print(ret) 

    生成器表达式

    g = (i for i in range(10))
    print(g)
    for i in  g:
        print(i)
    生成器表达式

    只要含有yield关键字的函数都是生成器函数  yield不能和return共用且需要写在函数内

    def generator():
        print(1)
        yield 'a'

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

    ret = generator()
    print(ret)
    print(ret.__next__())
    
    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)
    生成器函数一
    def wahaha():
        for i in range(2000000):
            yield '娃哈哈%s'%i
    g = wahaha()
    g1 = wahaha()
    print(g.__next__())
    print(g1.__next__())
    
    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
    生成器函数二

    生成器函数

    def generator():
        print(123)
        content = yield 1
        print('=======', content)
        print(456)
        arg = yield 2
        ''''''
        yield
    
    
    g = generator()
    ret = g.__next__()
    print('*', ret)
    
    ret = g.send('hello')  # send的效果和next一样
    print('*', ret)
    生成器函数三 

    send方法

    send 获取下一个值的效果和next基本一致
    只是在获取下一个值的时候,给上一yield的位置传递一个数据
    使用send的注意事项
        第一次使用生成器的时候 是用next获取下一个值
        最后一个yield不能接受外部的值
    

    获取移动平均值

    def wrapper(func): #在调用被装饰生成器函数的时候首先用next激活生成器
        def inner(*args, kwargs):
            ret = func(*args, kwargs)
            next(ret)
            return ret
        return inner
    
    
    @wrapper
    def average():
        sum = 0
        count = 0
        avg = 0
        while True:
            num = yield avg
            sum += num    # 10
            count += 1    # 1
            avg = sum / count
    
    
    avg_g = average()
    print(avg_g.send(10))
    print(avg_g.send(20))
    print(avg_g.send(30))
    获取移动平均值

    生成器小练习

    处理文件,用户指定要查找的文件和内容,将文件中包含要查找内容的每一行都输出到屏幕

    def check_file(filename, aim):
        with open(filename, mode='r', encoding='utf-8') as f:  # 句柄 : handler,文件操作符,文件句柄
            for i in f.readlines():
                if aim in i:
                    yield i
    
    
    g = check_file('test.py', 'def')
    for i in g:
        print(i.strip())

    写生成器,从文件中读取内容,在每一次读取到的内容之前加上‘*’之后再返回给用户

    def check_file(filename):
        with open(filename, mode='r', encoding='utf-8') as f:  # 句柄 : handler,文件操作符,文件句柄
            for i in f.readlines():
                yield '*' + i
    
    
    g = check_file('test.py')
    for i in g:
        print(i.strip())

    迭代器

    迭代

    迭代:可以将某个数据集内的数据“一个挨着一个的取出来”,就叫做迭代。
    字符串、列表、元组、字典、集合都可迭代对象
    可迭代协议:可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法
    迭代器:内部含有__next__和__iter__方法的就是迭代器
    可迭代的.__iter__()方法就可以得到一个迭代器
    迭代器中的__next__()方法可以一个一个的获取值
    

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

    l = ["12", '120', '119', '112', '10086', '10000']
    iterator = l.__iter__()
    print(iterator)
    print(iterator.__next__())
    
    #只要是能被for循环的数据类型 就一定拥有__iter__方法
    print([].__iter__())
    # 一个列表执行了__iter__()之后的返回值就是一个迭代器
    print(dir([]))
    print(dir([].__iter__()))
    print(set(dir([].__iter__())) - set(dir([])))
    print([1,'a','bbb'].__iter__().__length_hint__())  #元素个数
    l = [1,2,3]
    iterator = l.__iter__()
    print(iterator.__next__())
    print(iterator.__next__())
    print(iterator.__next__())
    print(iterator.__next__())

    迭代器的好处

    从容器类型中一个一个的取值,会把所有的值都取到。
    节省内存空间
    迭代器并不会在内存中再占用一大块内存,
    而是随着循环 每次生成一个
    每次next每次给我一个
    

    迭代器和生成器

    迭代器

    双下方法 : 很少直接调用的方法。一般情况下,是通过其他语法触发的
    可迭代的 —— 可迭代协议 含有__iter__的方法('__iter__' in dir(数据))
    可迭代的一定可以被for循环
    迭代器协议: 含有__iter__和__next__方法
    迭代器一定可迭代,可迭代的通过调用iter()方法就能得到一个迭代器
    迭代器的特点:
        方便逐个取值,一个迭代器只能取一次。
        节省内存空间
    

    生成器

    生成器的本质就是迭代器
    生成器的表现形式
        生成器函数
        生成器表达式
    生成器函数:
        含有yield关键字的函数就是生成器函数
        特点:
            调用函数的之后函数不执行,返回一个生成器
            每次调用next方法的时候会取到一个值,遇见yield就停止
            直到取完最后一个,在执行next会报错
        取值:
            for :如果没有break会一直取直到取完
            next :每次只取一个
            send :不能用在第一个,取下一个值的时候给上个位置传一个新的值
            数据类型强制转换 :会一次性把所有数据都读到内存里
    生成器表达式
            (条件成立想放在生成器中的值 for i in 可迭代的 if 条件)
    

    写生成器实现:有一个文件,从文件里分段读取内容 readline read(10) 在读出来的内容前面加上一个'*',再返回给调用者  

    def generator():
        for i in range(20):
            yield '哇哈哈%s' % i
    
    
    g = generator() #调用生成器函数得到一个生成器
    print(list(g))
    ret = g.__next__()   #每一次执行g.__next__就是从生成器中取值,预示着生成器函数中的代码继续执行
    print(ret)
  • 相关阅读:
    【转】80后安稳上班,90后看心情上班,95后……太形象了!
    未解决问题列表
    从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行。请采用循环控制语句来实现。
    按要求编写Java应用程序。 编写一个名为Test的主类,类中只有一个主方法; 在主方法中定义一个大小为50的一维整型数组,数组名为x,数组中存放着{1, 3,5,…,99}输出这个数组中的所有元素,每输出十个换一行;在主方法中定义一 个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’;输出这个数组中的所有元素。
    找出如下数组中最大的元素和最小的元素, a[][]={{3,2,6},{6,8,2,10},{5},{12,3,23}}
    已知2个一维数组:a[]={3,4,5,6,7},b[]={1,2,3,4,5,6,7};把数组a与数组b ,对应的元素乘积再赋值给数组b,如:b[2]=a[2]*b[2];最后输出数组b的元素。
    用自己的算法实现startsWith和endsWith功能。
    采用字符的移位方式实现字符文本加密解密。
    生成4位验证码,最多输入5次
    二分查找(转载的别人的,看的不是太懂)
  • 原文地址:https://www.cnblogs.com/zhangcheng94/p/12182412.html
Copyright © 2011-2022 走看看