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

    迭代器

    iterable

    l1=[1,1,1,1,1,1,1,1,1]#列表
    l2=l1.__iter__()  #迭代器
    print("__iter__" in dir(l1))#查看是否是可迭代对象的方法
    print("__iter__" in dir(l2))
    #上面列表和迭代器这两个都是可以迭代的对象.
    print("__next__" in dir(l1))#不是迭代器
    print("__next__" in dir(l2))#是迭代器
    print(l1.__next__())报错
    print(l2.__next__())迭代器的三个意义
    代码演示

    迭代器的意义

    因为是逐行循环的所以节省内存,

    有惰性机制

    迭代器不能反复,从头向下执行,执行到哪里就会是哪里,往后不会从头开始执行

    try异常处理

    try:

    要输入的异常错误代码

    except:

    break

    生成器

    本质其实其迭代器,其实是用代码编写的迭代器

    三种方式

    1,可以用生成器函数

    关键字

    yield

    yield和return的却别

    1.返回调用的值并停留在当前的位置.

    def func():
        print(11,1,1,1,1,1)
        yield
    print(func())#简单的生成器
    <generator object func at 0x0000020C2D1D8780>是其结果
    View Code

    2,可以用各种推导公式

    3.可以用数据转换

    send和next的用法一样

    __send__

    给上一个yeild返回一个值,不能用在最后一个和第一个.

    生成器的三种方法

    1.生成器函数

    yield函数可以生成一个生成器

    2.各种推导公式

    l2=[i for i in rang (111)]

    l2=[i for i in range(111) if ]

    3.数据转化的生成器

    转化为列表元组,

    list()tuple()

    迭代器、生成器

     

    1、迭代器

    可迭代对象:它的方法含有__iter__,可被for循环的对象。

    for循环 str list tuple dict set 文件句柄

    ①可迭代对象(iterable)与迭代器(iterator)的关系:

    可迭代对象---->迭代器:可迭代对象.__iter__()    迭代器遵循迭代器协议。

    迭代器取值:s.__next__()  每次取一个值。

    可迭代对象和迭代器区别:只含有__iter__方法的数据是可迭代对象,含有__iter__方法并且含有__next__方法的数据是迭代器。

    ②可迭代对象判断方法:

    方法一:dir(被测试对象),print('__iter__' in dir(s)),如果它的方法含有__iter__,那这个对象就叫做可迭代对象。遵循可迭代协议。

    方法二:测试它是迭代器还是可迭代对象。

    1
    2
    3
    4
    5
    6
    = [1,2,3,4]
    l_iter = l.__iter__()
    from collections import Iterable  #可迭代对象
    from collections import Iterator   #迭代器
    print(isinstance(l,Iterable))
    print(isinstance(l,Iterator))

     

    ③迭代器的特点。

    Ⅰ 节省内存

    Ⅱ迭代器惰性机制

    Ⅲ迭代器不能反复,一直向下执行。不可逆。

    ④for循环的内部机制。

    for循环的内部含有__iter__方法,它会将可迭代对象先转化成迭代器,然后再调用__next__方法取值,它有异常处理的方法。

    ⑤可迭代对象:str list tuple dict set 

    迭代器:文件句柄

    2、生成器

    生成器的本质就是迭代器,生成器是自己用Python代码写的迭代器。

    含有yield就是生成器。

    (1)用生成器函数写生成器。

    1
    2
    3
    4
    5
    6
    #生成器函数
    def gener():
        print(111)
        yield 222
    = gener()
    print(g)

    .__next__()遇到yield停住,可以再一次.__next__()来继续执行,如果.__next__()找不到下一个yield就会报错。

    send和.__next__功能一样,但是send会给上一个yield整体发送一个值,所以最后一个yield永远得不到send发送的值,获取第一个值的时候不能用send只能用next

    注:

    return和yield区别:

    return返回给调用者值,并结束此函数。

    yield返回给调用者值,并将指针停留在当前位置。

    (2)推导式/生成器表达式构建迭代器。

    ①列表推导式

    Ⅰ 列表推导式(循环模式):[变量(加工后的数据)for 变量i in 可迭代的数据类型]

    l2 = ['python%s期'%i for i in range(1,11)]
    print(l2)

    Ⅱ列表推导式(筛选模式):[变量(加工后的数据)for 变量i in 可迭代的数据类型 if 条件]

    l3 = [i for i in range(31) if i %3 ==0]    #30以内能被3整除的数
    print(l3)
    #找到嵌套列表中名字含有两个‘e’的所有名字
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    print([name for lst in names for name in lst if name.count('e') >= 2]) 

    列表推导式比较直观,占内存。生成器表达式(for循环)不容易看出内容,但是省内存。

    ②字典推导式

    #将一个字典的key和value对调
    mcase = {'a': 10, 'b': 34}
    mcase_frequency = {mcase[k]: k for k in mcase}
    print(mcase_frequency)

     

    #合并大小写对应的value值,将k统一成小写
    mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
    mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys()}
    print(mcase_frequency)

    ③集合推导式

    #计算列表中每个值的平方,自带去重功能
    squared = {x**2 for x in [1, -1, 2]}
    print(squared)
    # Output: set([1, 4])

    (3)可以通过数据转化

     list()和tuple()将生成器对象转化,一般不需要。

  • 相关阅读:
    Java中@Override注解的作用
    JAVA8 双冒号::的作用
    JAVA8 Stream
    梯度下降法推导,凸函数,收敛性推导
    Maven基础
    Openflow协议详解
    KeepAlive--高可用解决方案
    Spring Cloud Alibaba:Seata基础知识
    Spring Cloud Alibaba:Sentinel初始化监控和流控
    Spring Cloud Alibaba:Nacos配置中心
  • 原文地址:https://www.cnblogs.com/cangshuchirou/p/8422615.html
Copyright © 2011-2022 走看看