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

    可迭代对象:

           可以被 for 循环都是可迭代的

      拥有__iter__方法  ----可迭代协议

      特点:惰性运算

      例如:range(),str,list,tuple,dict,set

    迭代器Iterator:

      拥有__iter__方法和__next__方法     ---迭代器协议

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

      例如:iter(range()),iter(str),iter(list),iter(tuple),iter(dict),iter(set),reversed(list_o),map(func,list_o),filter(func,list_o),file_o

      迭代器的好处:

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

    生成器Generator:

      本质:迭代器,所以拥有__iter__方法和__next__方法

      特点:惰性运算,开发者自定义

    使用生成器的优点:

    1.延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。

    # 生成器 —— 迭代器
    # 生成器函数
    # 含有yield关键字的函数都是生成器函数
    # 生成器函数的特点
    #调用之后函数内的代码不执行,返回生成器
    #每从生成器中取一个值就会执行一段代码,遇见yield就停止。
    #如何从生成器中取值:
    # for :如果没有break会一直取直到取完
    # next :每次只取一个
    # send :不能用在第一个,取下一个值的时候给上个位置传一个新的值
    # 数据类型强制转换 :会一次性把所有数据都读到内存里

    #特点:
    #调用函数的之后函数不执行,返回一个生成器
    #每次调用next方法的时候会取到一个值
    #直到取完最后一个,在执行next会报错

    #生成器函数
    # def generator():
    #     print(1)
    #     return 'a'
    #
    # ret = generator()
    # print(ret)
    
    #只要含有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)
    
    #娃哈哈%i
    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
    View Code

    生成器表达式
    # (条件成立想放在生成器中的值 for i in 可迭代的 if 条件)

    监听列子

    def jt(filename):
        f = open(filename,encoding='utf-8')
        while True:
            line = f.readline()
            if line.strip():
                yield line.strip()
    
    g = jt('file')
    for i in g:
        if 'python' in i:
            print('***',i)
    View Code

    send

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

    获取移动平均值

    # avg = sum/count
    # 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()
    # avg_g.__next__()
    # avg1 = avg_g.send(10)
    # avg1 = avg_g.send(20)
    # print(avg1)
    View Code

    预激生成器的装饰器

    # 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)
    View Code

    yield from

    #python 3
    # def generator():
    #     a = 'abcde'
    #     b = '12345'
    #     for i in a:
    #         yield i
    #     for i in b:
    #         yield i
    # def generator():
    #     a = 'abcde'
    #     b = '12345'
    #     yield from a
    #     yield from b
    #
    # g = generator()
    # for i in g:
    #     print(i)
    View Code

    生成器表达式

    #[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] #遍历之后挨个处理
    #[满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件] #筛选功能

    生成器表达式
    1. 
    print([i*i for i in range(10)])
    翻译如下
    
    # g = (i for i in range(10))
    # print(g)
    # for i in  g:
    #     print(i)
    View Code
    # #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)
    #
    # #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)
    #
    # # 例三:找到嵌套列表中名字含有两个‘e’的所有名字
    # names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
    #          ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    # ret = [name for lst in names for name in lst if name.count('e') ==2]
    # ret = (name for lst in names for name in lst if name.count('e') ==2)
    # print(ret)
    
    #字典推导式
    
    
    # 例一:将一个字典的key和value对调
    # mcase = {'a': 10, 'b': 34}
    # #{10:'a' , 34:'b'}
    # mcase_frequency = {mcase[k]: k for k in mcase}
    # print(mcase_frequency)
    
    # 例二:合并大小写对应的value值,将k统一成小写
    # mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
    # #{'a':10+7,'b':34,'z':3}
    # mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase}
    # print(mcase_frequency)
    
    #集合推导式,自带结果去重功能
    # squared = {x**2 for x in [1, -1, 2]}
    # print(squared)
    View Code
    # 3.处理文件,用户指定要查找的文件和内容,将文件中包含要查找内容的每一行都输出到屏幕
    # def check_file(filename,aim):
    #     with open(filename,encoding='utf-8') as f:   #句柄 : handler,文件操作符,文件句柄
    #         for i in f:
    #             if aim in i:
    #                 yield i
    #
    # g = check_file('1.复习.py','生成器')
    # for i in g:
    #     print(i.strip())
    
    # 4.写生成器,从文件中读取内容,在每一次读取到的内容之前加上‘***’之后再返回给用户。
    # def check_file(filename):
    #     with open(filename,encoding='utf-8') as f:   #句柄 : handler,文件操作符,文件句柄
    #         for i in f:
    #             yield '***'+i
    #
    # for i in check_file('1.复习.py'):
    #     print(i.strip())
    View Code
    def add(n, i):
        return n+i
    
    def test():
        for i in range(4):
            yield i
    g = test()                        
    for n in [1,10,5]:                 #  n = 1
        g =(add(n, i) for i in g)      #  g =  add(n, i) for i in g   # 其中 g = test() 如下
            #分解for循环     >>>       #  g =  add(n, i) for i in test()
                                       #  n = 10
                                       #  g = add(n, i) for i in g # 其中 g = add(n, i) for i in test() 如下
                                       #  g = add(n, i) for i in add(n, i) for i in test()
                                       #  n = 5
                                       #  g = add(n, i) for i in g #  其中 g =add(n, i) for i in add(n, i) for i in test()如下
                                       #  g = add(n, i) for i in 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()
    #test() = (0,1,2,3)
    #g = add(n, i) for i in add(n, i) for i in add(n, i) for i in (0,1,2,3)
    #g = add(n, i) for i in add(n, i)for i in (5,6,7,8)
    #g = add(n, i) for i in (10,11,12,13)
    #g = (15,16,17,18)
    print(list(g))
    
    
    
    
    
    
    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))  # g = demo() -> g 是生成器,list强转 list(g) = [0,1,2,3] g已经把生成器的值都取完了,生成器的特点,只能取一次值
                       #   所以后面的再取值 就是一个空的列表了,已经没有值了
    print(list(g1))  
    print(list(g2))
    View Code
  • 相关阅读:
    第一次作业(2)
    第0次作业(2)
    最后一次作业—总结报告
    第八次作业
    第七周作业
    第六周作业
    第四周作业
    第4次作业
    2018c语言第3次作业
    2018c语言第2次作业
  • 原文地址:https://www.cnblogs.com/bzluren/p/10645985.html
Copyright © 2011-2022 走看看