首页 > 其他 > 详细

三、生成器/迭代器

时间:2020-11-27 22:27:33      阅读:35      评论:0      收藏:0      [点我收藏+]

思考:

技术分享图片

一、迭代器/可迭代对象

 1.可迭代对象(费内存)

老版本python:range比较费内存(需要多少数据,全部存在list中,在数据量比较大的情况下非常耗内存)

技术分享图片

range实现过程:

from typing import Iterable

def range_test(stop):
    start = 0
    result = []
    while start < stop:
        result.append(start)
        start += 1
    return result


if __name__ == __main__:
    print(isinstance(range_test(10),Iterable))  # 判断返回结果是不是可迭代,True
    print(range_test(10))                     # output:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

 2.可迭代对象(省内存)

 

from typing import Iterable

# Next含有__next__()方法,每次变量+1,一次只占用一个数的内存
class Next(object):
    """Next class"""

    def __init__(self, stop, start=-1):
        self.start = start
        self.stop = stop

    def __next__(self):
        if self.start >= self.stop - 1:
            raise StopIteration
        self.start += 1
        return self.start

 

# 含有__iter__()方法,return调用Next
class MyRange:

    def __init__(self, stop):
        self.stop = stop

    def __iter__(self):
        return Next(self.stop)

 使用调式模式,单步执行,可看到程序执行Next,每执行一次,生成一个数据。不耗内存

 for是迭代(自动执行__iter__,__next__),while是循环(手动指定函数)

if __name__ == __main__:
    print(Next(10).__next__())  # 0
    for item in MyRange(10):  # for循环自动执行__iter__,__next__方法
        print(item)
    # while循环
    num = MyRange(10).__iter__()
    i = 0
    while i < 10:
        print(num.__next__())  # 0,1,2,3,4,5,6,7,8,9
        i += 1

3.可迭代对象定义

可以被for迭代的对象都是可迭代对象

对象有__iter__方法的,都是可迭代对象(如果没有__iter__方法,他不可以被for迭代),__iter__要求返回值必须是一个迭代器(严格来说,返回值必须有__next__方法)

常见的可迭代对象;list、tuple、string、dict

判断某个每个对象是不是可迭代对象:

  1. 可通过dir()查看所有属性中是否有__iter__方法

  2. 也可以通过hasattr(list,‘__iter__‘),查看list是否有__iter__方法。返回True则说明有该方法

判断MyRange(10)是否是可迭代对象:

print(isinstance(MyRange(10),Iterable)   返回True,则MyRange(10)是可迭代对象,因为有__iter__方法

判断Next(10)是否是可迭代对象:

print(isinstance(Next(10),Iterable)   返回False,则Next(10)不是可迭代对象,因为没有__iter__方法

4.迭代器定义

迭代器必须__iter_ __next__  属性

核心:通过 __next__方法记住迭代的位置,有没有迭代完毕

迭代器是特殊的可迭代对象,

可以被for迭代,for迭代迭代器时,会自动执行__next__方法

迭代器比较省内存,一次只给一个数。

没有迭代器,则用不了for,只能用while

判断Next(10)是否是迭代器

print(isinstance(Next(10),Iterator)    # Fasle  因为虽然有__next__方法,但是缺少__iter__方法

注意:__iter__必须返回一个迭代器(严格来说,返回值必须有__next__方法)

二、生成器

因为迭代器手工实现比较麻烦

所以python提供了生成器对象,生成器对象的目的就是获得迭代器对象(非常高效)

def fun():
    print("在yield1前面")
    yield 1
    print("在yield1后面,yield2前面")
    yield 2


if __name__ == __main__:
    # 验证是否是生成器
    print(fun())   # <generator object fun at 0x104d00150> 结果是一个生成器对象,但是没有运行函数
    print(hasattr(fun(),"__iter__"))  # True
    print(hasattr(fun(),"__next__"))  # True

    # 运行生成器,必须要调用__next__
    print(fun().__next__())  # 1 / 在yield1前面
    
    # 运行出全部结果,for自动调用__next__
    for i in fun():
        print(i)

注意:

  • 当python解释器看到函数中有yield的时候,不会立即去调用这个函数,而是先创建一个生成器对象。而这个生成器对象会记住函数的状态

  • 在for循环中,运行到第一个yield时,就暂时退出了(类似return,但区别是return是永久跳出不会再回去了)。再次运行时(__next__记住位置),会从yield1后面开始运行

  • 当执行next(生成器对象)时,会执行生成器对象的yield.

生成器是特殊的迭代器,迭代器是特殊的可迭代对象

生成器是可迭代对象

如果创建生成器对象(通过yield)

yield:关键字

记住函数执行的状态

当执行next(g)时,会执行g中的yield

yield和return的区别:

return:跳出函数,不回来了

yield:暂时跳出,还会回来

生成器的使用场景:

技术分享图片 

生成器为什么省内存:因为有__next__

生成器是为了快速获得含有__iter__  __next__的方法

场景一:我需要99999999999个数字,一下子把1——9999999999999个数字放到list中

场景二:我需要99999999999个数字,需要1生成1,需要2生成2~~~~~需要999999999999生成999999999999

场景二是next思想(生成器、迭代器)

 

转载仅供参考:http://testingpai.com/article/1605148018144 

三、生成器/迭代器

原文:https://www.cnblogs.com/zhangjx2457/p/14038475.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!