• python基础15下_迭代器_生成器


    print(dir([]))   #告诉我列表拥有的所有方法
    # 双下方法
    # print([1].__add__([2]))
    print([1]+[2])
    
    ret = set(dir([]))&set(dir({}))&set(dir(''))&set(dir(range(10)))
    print(ret)  #iterable
    
    print('***'.center(50,'-'))
    # 只要是能被for循环的数据类型 就一定拥有__iter__方法
    print('__iter__' in dir(int))
    print('__iter__' in dir(bool))
    print('__iter__' in dir(list))
    print('__iter__' in dir(dict))
    print('__iter__' in dir(set))
    print('__iter__' in dir(tuple))
    print('__iter__' in dir(enumerate([])))
    print('__iter__' in dir(range(1)))
    
    # Iterable  可迭代的    -- > __iter__  # 只要含有__iter__方法的都是可迭代的
    # [].__iter__() 迭代器  -- > __next__  # 通过next就可以从迭代器中一个一个的取值
    
    # 只要含有__iter__方法的都是可迭代的 —— 可迭代协议
    
    # 迭代器的概念
    # 迭代器协议 —— 内部含有__next__和__iter__方法的就是迭代器
    
    # 迭代器协议和可迭代协议
    # 可以被for循环的都是可迭代的
    # 可迭代的内部都有__iter__方法
    # 只要是迭代器 一定可迭代
    # 可迭代的.__iter__()方法就可以得到一个迭代器
    # 迭代器中的__next__()方法可以一个一个的获取值
    
    from collections import Iterable
    from collections import Iterator
    print('****'.center(50,'_'))
    print(isinstance([],Iterator))    # False 不是迭代器
    print(isinstance([],Iterable))    # True  是可迭代的
    
    #迭代器的好处:
        # 从容器类型中一个一个的取值,会把所有的值都取到。
        # 节省内存空间
            #迭代器并不会在内存中再占用一大块内存,
                # 而是随着循环 每次生成一个
                # 每次next每次给我一个
    # 生成器 —— 迭代器
    # 生成器函数 —— 本质上就是我们自己写得函数
    # 生成器表达式
    
    #只要含有yield关键字的函数都是生成器函数
    # yield不能和return共用且需要写在函数内
    def generator():
        print(1)
        yield 'a'
    
    # #生成器函数 : 执行之后会得到一个生成器作为返回值
    ret = generator()       # 拿到生成器
    print(ret)              # 打印内存地址
    print(ret.__next__())   # 执行函数体,直到遇到 yield
    
    def generator2():
        print(111)
        yield 'aaa'
        print(222)
        yield 'bbb'
        yield 'ccc'
    g = generator2()
    # for i in g:
    #     print(i)
    ret = g.__next__()
    print(ret)
    ret = g.__next__()
    print(ret)
    ret = g.__next__()
    print(ret)
    
    #娃哈哈%i
    def wahaha():
        for i in range(2000000):
            yield '娃哈哈%s'%i
    g = wahaha()
    g1 = wahaha()   # 两个独立的生成器
    print(g.__next__())
    print(g.__next__())
    print(g1.__next__())
    print(g1.__next__())
    
    
    gg = wahaha()
    count = 0
    for i in gg:
        count +=1
        print(i)
        if count > 50:
            break
    
    print('*******',gg.__next__())  # 生成器继续前面的往下走
    
    for i in gg:                    # 生成器继续前面的往下走
        count +=1
        print(i)
        if count > 100:
            break

    生成器与send方法

    # 从生成器中取值的几个方法
        # next
        # for
        # 数据类型的强制转换 : 缺点:占用内存
    
    
    
    def generator():
        print(123)
        content = yield 1
        print('=======',content)
        print(456)
        arg = yield 2
        ''''''
        yield
    g1 = generator()
    g2 = generator()
    g1.__next__()
    g2.__next__()
    print('>>>>>',generator().__next__())
    print('***',generator().__next__())
    
    g = generator()
    ret = g.__next__()
    print('***',ret)
    ret = g.send('hello')   # send的效果和next一样, 但是多了传递数据的功能
    print('***',ret)
    
    # send 获取下一个值的效果和next基本一致
    # 只是在获取下一个值的时候,给上一yield的位置传递一个数据
    # 使用send的注意事项
        # 第一次使用生成器的时候 是用next获取下一个值
        # 最后一个yield不能接受外部的值
    def generator():
        print(123)
        content = yield 1
        print('=======', content)
        print(456)
        yield 2
        ''''''
        yield
    
    
    g = generator()
    ret = g.__next__()
    print('+++', ret)
    res = g.send('hello')  # send的效果和next一样
    print('--->', res)
    
    
    # send 获取下一个值的效果和next基本一致
    # 只是在获取下一个值的时候,给上一yield的位置传递一个数据
    # 使用send的注意事项
    # 第一次使用生成器的时候 是用next获取下一个值
    # 最后一个yield不能接受外部的值
    
    
    # 案例应用: 获取移动平均值
    # 10 20 30 10
    # 10 15 20 17.5
    # avg = sum/count
    
    def avgs():
        sum = 0
        cnt = 0
        avg = 0
        while True:
            num = yield avg
            sum += num
            cnt += 1
            avg = sum / cnt
    
    
    g = avgs()
    g.__next__()
    avg1 = g.send(10)
    avg1 = g.send(8)
    print(avg1)
    avg2 = g.send(6)
    print(avg2)

    利用生成器来监视文件内容:

    # 文件内容监视
    def tail(filename):
        with open(filename,encoding='utf8') as f:
            while 1:
                line = f.readline()
                if line.strip():
                    # print(line)
                    yield line.strip()
    
    g = tail('file')
    for i in g:
        if 'python' in i:
            print('***',i)

    给生成器函数加上装饰器,省掉一步 __next__()

    # 预激生成器的装饰器
    def init(func):  # 装饰器
        def inner(*args, **kwargs):
            g = func(*args, **kwargs)  # g = average()
            g.__next__()
            return g
    
        return inner
    
    
    @init
    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()  # ===> inner
    ret = avg_g.send(10)
    print(ret)
    ret = avg_g.send(20)
    print(ret)

    直接 yield from 

    def gen():
        a = 'abcdef'
        b = '12345'
        yield from a   # 直接对容器类型生成器
        yield from b
    
    
    g = gen()
    # for i in g:
    #     print(i)
    
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())

    两个生成器的小例子:

    # 3.处理文件,用户指定要查找的文件和内容,将文件中包含要查找内容的每一行都输出到屏幕
    def check_file(filename, txt):
        with open(filename, encoding='utf8') as f:
            for i in f:
                if txt in i:
                    yield i
    
    
    g = check_file('a.txt', '正当防卫')
    for i in g:
        print(i.strip())
        
    
    # 4.写生成器,从文件中读取内容,在每一次读取到的内容之前加上‘***’之后再返回给用户。
    def read_file(filename):
        with open(filename, encoding='utf-8') as f:  # 句柄 : handler,文件操作符,文件句柄
            for i in f:
                yield '***' + i
    
    
    for i in read_file('a.txt'):
        print(i.strip())

    生成器表达式遇到循环

    def demo():
        for i in range(4):
            yield i
    
    
    g = demo()
    
    g1 =(i for i in g)
    g2 =(i for i in g1)
    #  以上所有都没干活
    
    # print(list(g)) # 如果这里list了,则下面两个都取不到值,因为已经空了。
    print(list(g1))  # list 取走了所有 g1 的值
    print(list(g2))  # g2 已经空了,没有值
    
    
    #### 生成器表达式 循环
    def add(n,i):
        return n+i
    
    def test():
        for i in range(4):
            yield i
    
    g=test()
    for n in [1,10,5]:
        g=(add(n,i) for i in g)
    
    # 遇到上面的for循环生成器表达式,就把它拆开如下:
    # n = 1
    # g=(add(n,i) for i in test())
    # n = 10
    # g=(add(n,i) for i in (add(n,i) for i in test()))
    # n = 5
    # g=(add(n,i) for i in (add(n,i) for i in (add(n,i) for i in test())))
    # 上面一句的结果 g=(15,16,17,18)
    
    print(list(g))  # [15,16,17,18]
  • 相关阅读:
    WPF学员管理系统
    dotnet-千星项目OpenAuthNet基于NetCore21的快速开发框架
    MVC5仓库管理系统
    华为设备IPC V200R002C0SPC SDK连接demo
    基础界面
    交通建设项目管理信息化系统
    Apache常见interview
    mamcached+(magent+keepalived高可用)搭建及理论概述
    TCP/IP三次挥手,四次断开(精简)
    简述FTP的主动模式与被动模式(精简)
  • 原文地址:https://www.cnblogs.com/frx9527/p/yield_from.html
Copyright © 2020-2023  润新知