zoukankan      html  css  js  c++  java
  • python:迭代器,生成器

    可迭代对象:内部含有‘__iter__’方法的对象

    优点:

    存储的数据可以直接显示,比较直观

    拥有的方法比较多

    缺点:

    占用内存

    不能直接for循环取值,是通过内部转化成迭代器

    # dir():获取一个对象的所有方法
    s1 = 'abcde'
    print(dir(s1))    # 输出一个list,内容是s1对象的所有方法,每个方法以字符串形式输出
    print('__iter__' in dir(s1))    # 判断一个对象是否是可迭代对象

    迭代器

    '''
    迭代器:内部含有'__iter__'并且含有'__next__'方法的对象就是迭代器
    因为迭代器的内部含有'__next__'方法,所有可以通过for循环取值
    判断一个对象是否是迭代器:'__iter__' in dir(f1) and '__next__' in dir(f1)
    利用iter(object)/object.__iter__()形成一个迭代器,对迭代器进行操作可以节省内存
    利用next(object)/object.__next__()取值,一次只取一个
    迭代就是数据处理的基石,扫描内存中放不下的数据集时,我们要找到一种惰性获取数据项的方式,即按需一次获取一个数据项,这就是迭代器模式
    优点:
        节省内存
        惰性机制:next一次取一个值,下一次next再取下一个值
    缺点:
        不能直观的查看里面的数据
        速度慢
        取值不能回头
    '''

    可迭代对象转化成迭代器

    s = [11,22,33,44]
    obj = s.__iter__()    # 等同于iter(s),利用s形成一个迭代器,赋值给obj
    print(s)    # [11, 22, 33, 44]
    print(obj)    # <list_iterator object at 0x00000000026191D0>
    
    s = [11,22,33,44]
    obj = s.__iter__()
    print(obj.__next__())    # 11,等同于next(obj),迭代器利用 '__next__()'方法取值,一次只取一个值
    print(next(obj))        # 22
    print(obj.__next__())    # 33
    
    # 利用while循环 模拟for循环对可迭代对象取值
    s  = [11,22,33,44,55,66,77,88]
    obj = iter(s)
    while 1:
        try:
            print(next(obj))
        except StopIteration:
            break
    s  = [11,22,33,44,55,66,77,88,99]
    obj = iter(s)
    for i in range(4):
        print(next(obj))
    for j in range(4):
        print(obj.__next__())

    生成器

    生成器:可以用迭代器看着是一种, 生成器的本质就是迭代器

    生成是我们自己用python代码构建的数据结构,迭代器是python提供的,或者转化来的

    获取生成器三种方式:

      通过生成器函数自己写

      通过生成器表达式自己写

      python内部提供

    # 只要函数中有 yield,那么它就是生成器函数,一个生成器函数可以存在多个yield
    # yield不会结束函数的执行,只是暂停函数
    def fun():
        print(111)
        yield 3        # 一个next(),代码就会执行到这里,并且将3返回,后面的代码不执行,直到下一个next()
        print(222)
        yield 4    
    ret = func() # 因为函数中有yield,所以是生成器函数,所以这里并不会执行函数中的代码
    print(ret)    # <generator object fun at 0x00000000025F8570> 生成器对象
    print(next(ret))    # 111 3 生成器中一个next,对应一个yield,
    print(next(ret))    # 第一个yield执行完,就会执行这里的next,接着执行函数中第一个yield后面的代码
    # 吃包子例子
    def func():
        for i in range(1,50):
            yield f'{i}号包子'
    ret = func()
    for i in range(10):
        print(next(ret))

    yield from 将一个可迭代对象变成一个生成器

    def func():
        l1 = [1,2,3,4,5]
        yield l1
    ret = func()  
    print(ret)    # <generator object func at 0x0000000002408570>
    print(next(ret))    # [1, 2, 3, 4, 5]
    
    def func1():
        l2 = [1,2,3,4,5]
        yield from l2    # yield from 将list 变成一个生成器
    ret = func1()    # 返回一个生成器对象赋值给ret
    for i in ret:    # 利用for循环对生成器对象直接取值,
        print(i)
        
        
    def func():
        list1 = [1,2,3,4,5]
        list2 = [6,7,8,9,0]
        yield from list1
        yield from list2
    ret = func()
    for i in ret:
        print(i)    # 1 2 3 4 5 6 7 8 9 0

    生成器表达式 获取生成器

    ret = (i for i in range(1,11))
    print(ret)        # <generator object <genexpr> at 0x00000000023E8570> 
    for i in ret:
        print(i)

    让生成器产出值的三种方式:next(),for循环,list(),本质都是调用next()

    # list(generator) ,将生成器对象转化成list
    def chain(*iterables):
        for it in iterables:
            for i in it:
                yiled i
    ret = chain('abc',(1,2,3))
    print(ret)    # <generator object chain at 0x00000000025F8570>
    print(list(ret))    # ['a', 'b', 'c', 0, 1, 2]
    
    def chain(*iterables):
        for it in iterables:
            yield from it
    ret = chain('abc',(1,2,3))
    print(list(ret))    # ['a', 'b', 'c', 0, 1, 2]
  • 相关阅读:
    Xlua侧如何接受CSharp侧的可变参数
    C# 中如何精确地测量一段逻辑的执行时间
    C#中设计一个 ListPool 的方案
    unity中获取设备的信息
    Oracle-游标-取钱-存钱-转账
    Oracle 存储过程与java调用
    PL/SQL loop,while.for循环
    PL/SQL if case when
    PL/SQL %type %rowtype
    Oracle PLSQL入门
  • 原文地址:https://www.cnblogs.com/jmuchen/p/13381787.html
Copyright © 2011-2022 走看看