• Python 迭代器和生成器


    什么时候迭代器?

    现在,我们已经获得了一个新线索,有一个叫做“可迭代的”概念

    首先,我们从报错来分析,好像之所以1234不可以for循环,是因为它不可迭代。那么如果“可迭代”,就应该可以被for循环了。

    这个我们知道呀,字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的

    迭代器 = 可迭代对象.__iner__() 或者iter(可迭代对象),自带一个__next__()方法

    迭代器的优势:节省内存,效率高,每次只取一个值,而不需要所有的值都取出来之后再进行计算

    from collections import Iterable

    l = [1, 2, 3, 4]
    t = (1, 2, 3, 4)
    d = {1: 2, 3: 4}
    s = {1, 2, 3, 4}

    print(isinstance(l, Iterable))--->True
    print(isinstance(t, Iterable))--->True
    print(isinstance(d, Iterable))--->True
    print(isinstance(s, Iterable))--->True

    迭代器的特性:惰性计算,找他next要值才给,不要不给

    生成器(generator):自己写的迭代器就是生成器,两种自己写生成器(迭代器)的机制,生成器函数、生成器表达式
    生成器函数:
    def cloth_g(num):
    for i in range(num):
    yield 'cloth%s'%i
    g = cloth_g(10)
    print(next(g))
    print(next(g))
    1.凡是带有yield关键字的函数,就是一个生成器函数
    2.生成器函数的调用不会触发函数的执行,而会返回一个生成器(迭代器)
    3.生成器函数的执行需要用next

    生成器监听文件输入的例子:
    def lister_file():
    with open('tmp') as f1:
    while True:
    for line in f1:
    if line.strip():
    yield line.strip()
    time.sleep(0.1)

    g = lister_file()
    for line in g:
    print(line)

    send,在执行next的过程中,传递一个参数给生成器函数的内部;
    想生成器中传递值 有一个激活的过程 第一次必须要用next触发这个生成器
    def func():
    print(1111)
    ret1 = yield 1
    print(222,'ret1:',ret1)
    ret2 = yield 2
    print(3333,'ret2:',ret2)
    yield 3


    g = func()
    print(next(g))
    print(g.send('alex'))
    print(g.send('金老板1'))
    
    
    计算移动平均值:
    def average():
    avg = 0
    day = 0
    sum = 0
    while True:
    money = yield avg
    sum += money
    day += 1
    avg = sum/day
    g = average()
    next(g)
    print(g.send(200))
    print(g.send(500))
    print(g.send(800))
     生成器函数: 是python程序员实现迭代器的一种手段
    主要特征:在函数体中有yield关键字
    调用生成器函数,不会执行这个函数中的代码,只是会获得一个生成器(迭代器)
    只有从生成器中取值的时候,才会执行函数内部的代码,且每获取一个数据才得到这个数据的代码
    获取数据的方式包括next send for循环(for i in g),数据类型的强制转换列表或者元组(l = list(g))
    yield返回值的简单方法,如果本身就是一个可迭代的,且要把可迭代对象中的每个数据返回,可以使用yield from
      def func():
      yield from range(5)
      g = func()
      print(next(g))
      print(next(g))
      print(next(g)) 输入结果为0,1,2
    在使用send的时候,在生成器创造出来之后需要进行预激活,这一步可以使用迭代器完成
    def init(f):
    def inner():
    ret = f()
    next(ret)#预激活
    return ret
    return inner

    @init
    def func():
    yield from range(5)

    g = func()
    print(next(g)) #输出结果为1
    生成器表达式:
    取出10以内的每个数的平方,添加到列表内
    常规操作:
    l = []
    for i in range(10):
      l.append(i**2)
    print(l)

    列表推导式和生成器表达式

    列表推导式:print([i**2 for i in rang(5)])

    推导式的套路

    
    

    之前我们已经学习了最简单的列表推导式和生成器表达式。但是除此之外,其实还有字典推导式、集合推导式等等。

    
    

    下面是一个以列表推导式为例的推导式详细格式,同样适用于其他推导式。

    
    
    variable = [out_exp_res for out_exp in input_list if out_exp == 2]
      out_exp_res:  列表生成元素表达式,可以是有返回值的函数。
      for out_exp in input_list:  迭代input_list将out_exp传入out_exp_res表达式中。
      if out_exp == 2:  根据条件过滤哪些值可以。

    例一:30以内所有能被3整除的数 print([i for i in range(30) if i%3 == 0])--->输出结果[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
    例二:30以内所有能被3整除的数的平方 print([i**2 for i in range(30) if i%3 == 0])--->输出结果[0, 9, 36, 81, 144, 225, 324, 441, 576, 729]
    例三:找到嵌套列表中名字含有两个‘e’的所有名字print(j for i in names for j in i if count('e') == 2)
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]

    print(j for i in names for j in i if j.count('e') == 2)

    练习题:

    例1:  过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母

    names = ['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe']

    print([i,upper() for i in names if len(i)>3])

    例2:  求(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元祖列表

    [(x,y) for x in range(5) if x%2==0 for y in range(5) if y %2==1] 

    例3:  求M中3,6,9组成的列表M = [[1,2,3],[4,5,6],[7,8,9]]

      l =  [row[2] for row in M] ---->列表推导式 print(l) --->[3, 6, 9]

     g = (row[2] for row in M)---->生成器表达式 print(g)----><generator object <genexpr> at 0x0000000002411BF8>

    for i in g:print(i)
    生成器的重点在于,有没有执行,一个生成器从头到尾只能取值一次,在不找他要值的时候始终不执行
    当他执行的时候,要以执行时候的所有变量值为准。








  • 相关阅读:
    DB-MySQL:MySQL 正则表达式
    DB-MySQL:MySQL 事务
    DB-MySQL:MySQL 索引
    DB-MySQL:MySQL 临时表
    DB-MySQL:MySQL 复制表
    DB-MySQL:MySQL 序列使用
    DB-MySQL:MySQL 处理重复数据
    DB-MySql:MySQL 及 SQL 注入
    mysql
    PHP+jQuery 注册模块的改进之一:验证码存入SESSION
  • 原文地址:https://www.cnblogs.com/xiaoAzaina/p/8954263.html
Copyright © 2020-2023  润新知