• 4 迭代器和生成器



    一 迭代器

    1.1 概念 

    # 凡是可以使用for循环取值的都是可迭代的
    # 可迭代协议 :内部含有__iter__方法的都是可迭代的,如list,dic,tuple,str,集合,range,文件,等都是可迭代的。
    # 迭代器协议 :内部含有__iter__方法和__next__方法的都是迭代器

    1.2 优势
    可迭代 最大的优势 节省内存

    迭代器优势:
    1节省内存
    2取一个值就能进行接下来的计算 ,而不需要等到所有的值都计算出来才开始接下来的运算

    1.3 例子

     1 这两个都是可迭代的,都会取到1,2,3
     2 
     3 lst_iter = [1,2,3].__iter__()
     4 print(lst_iter.__next__())
     5 print(lst_iter.__next__())
     6 print(lst_iter.__next__())
     7 
     8 
     9 for i in [1,2,3]:   
    10     print(i)

    二 生成器
    2.1 概念
    生成器 Generator
    # 自己写的迭代器 就是一个生成器
    # 两种自己写生成器(迭代器)的机制:生成器函数 生成器表达式

    凡是带有yield的函数就是一个生成器函数

    2.2优势

    同样是节省内存

    2.3 例子(生成器函数)

     1 # 生成器函数的调用不会触发代码的执行,而是会返回一个生成器(迭代器)
     2 # 想要生成器函数执行,需要用next
     3 
     4 def cloth_g(num):
     5     for i in range(num):
     6         yield 'cloth%s'%i
     7 
     8 
     9 g = cloth_g(1000)
    10 print(next(g))
    11 print(next(g))
    12 print(next(g))

     2.4 send关键字

     1 # send关键字
     2 def func():
     3     print(11111)
     4     ret1 = yield 1
     5     print(22222,'ret1 :',ret1)
     6     ret2 = yield 2
     7     print(33333,'ret2 :',ret2)
     8     yield 3
     9 
    10 
    11 g = func()
    12 ret = next(g)
    13 print(ret)
    14 print(g.send('alex'))  # 在执行next的过程中 传递一个参数 给生成器函数的内部
    15 print(g.send('金老板'))
    16 
    17 # 想生成器中传递值 有一个激活的过程 第一次必须要用next触发这个生成器

    2.5  预激活生成器 这样在下面函数执行的时候不用再next了,或者多个函数需要激活的时候,就适合方便用这种方法

     1 # 预激生成器
     2 # def init(func):
     3 #     def inner(*args,**kwargs):
     4 #         ret = func(*args,**kwargs)
     5 #         next(ret)  # 预激活
     6 #         return ret
     7 #     return inner
     8 #
     9 # @init
    10 # def average():
    11 #     sum_money = 0
    12 #     day = 0
    13 #     avg = 0
    14 #     while True:
    15 #         money = yield avg
    16 #         sum_money += money
    17 #         day += 1
    18 #         avg = sum_money/day
    19 #
    20 # g = average()
    21 # print(g.send(200))
    22 # print(g.send(300))
    23 # print(g.send(600))

    2.6 yield from

     1 第一种写法:
     2 def genrator():
     3     for i in range(5):
     4         yield i
     5     for j in ('hello'):
     6         yield j
     7 g = genrator()
     8 
     9 第二种写法:
    10 
    11 def generator_func():
    12     yield from range(5)
    13     yield from 'hello'
    14 g = genrator()

    2.7 如何从生产器中取值,三种


    # 第一种 :next 随时都可以停止 最后一次会报错
    # print(next(g))
    # print(next(g))
    # 第二种 :for循环 从头到尾遍历一次 不遇到break、return不会停止
    # for i in g:
    # print(i)
    # 第三种 :list tuple 数据类型的强转 会把所有的数据都加载到内存里 非常的浪费内存
    # print(g)
    # print(list(g))

    2.8生成器函数总结

    # 一个生成器 只能取一次
    # 生成器在不找它要值的时候始终不执行
    # 当他执行的时候,要以执行时候的所有变量值为准
    # 主要特征是 在函数中 含有yield
    # 调用一个生成器函数 不会执行这个函数中的带码 只是会获得一个生成器(迭代器)
    # 只有从生成器中取值的时候,才会执行函数内部的带码,且每获取一个数据才执行得到这个数据的带码
    # 获取数据的方式包括 next send 循环 数据类型的强制转化
    # yield返回值的简便方法,如果本身就是循环一个可迭代的,且要把可迭代数据中的每一个元素都返回 可以用yield from
    # 使用send的时候,在生成器创造出来之后需要进行预激,这一步可以使用装饰器完成
    # 生成器的特点 : 节省内存 惰性运算
    # 生成器用来解决 内存问题 和程序功能之间的解耦
    三列表推导式和生成器表达式
    区别就是中括号和小括号的区别
     1 ##列表推导式
     2 
     3 # print([i**2 for i in range(5)])
     4 #
     5 # l = [1,2,3,-5,6,20,-7]
     6 # print([abs(i) for i in l ])
     7 # print([i for i in l if i%2==1])
     8 ##被30整除数的平方
     9 # print([i**2 for i in range(30) if i%3 ==0])
    10 列表推导式
    11 [i**2 for i in range(30) if i%3 ==0]
    12 
    13 生成器表达式
    14 g = (i**2 for i in range(30) if i%3 ==0)
    
    
  • 相关阅读:
    服务器上的vhost
    php解压缩文件方法汇总
    STM32新起航-TMP1
    实现
    如何协调项目与领导?
    《致加西亚的一封信》读后感
    致加西亚的信
    本周设计部分及作业
    对·作业提交项目作业模块需求的编写(赵刚,段超凡)
    (第三周)团队模式中对交响乐团模式的理解
  • 原文地址:https://www.cnblogs.com/huningfei/p/8920759.html
Copyright © 2020-2023  润新知