美文网首页python 学习日记python自学
Python 生成器以及yield关键字

Python 生成器以及yield关键字

作者: 小黑天天快乐 | 来源:发表于2020-04-12 22:15 被阅读0次

    -->>>我的原文链接

    一、生成器

    首先提一个问题:

    range(5) 和list(range(5)) 有何区别?

    大家可以尝试在Python shell里键入这两个命令看看是何结果。没有意外的话,前者返回range(0,5),后者返回[0, 1, 2, 3, 4]。说明前者是一个range对象,后者是一个列表。

    这还不是关键,我们分别定义一个range和相应的列表,看看前后内存占用的变化。

    >>> print(psutil.Process(os.getpid()).memory_info().rss)
    18161664
    >>> x = list(range(10000000))
    >>> print(psutil.Process(os.getpid()).memory_info().rss)
    423337984 # 内存占用明显提升
    >>> y = range(100000000000)
    >>> print(psutil.Process(os.getpid()).memory_info().rss)
    423337984 # 内存占用几乎不变
    

    这其实就是生成器和普通列表的区别了。生成器在内存当中存储的是序列生成的逻辑,而我们一般用的列表,则是实实在在地把列表数据项放在内存里了。

    应该可以体会到,当我们进行大数据的处理时,这是有显著差异的。

    除此之外,我们再来看看处理时间,应该不难猜到,原理同上。

    import time
    
    t1 = time.time()
    x = range(1000000)
    t2 = time.time()
    y = list(range(1000000))
    t3 = time.time()
    
    print(f'Time consumed for using range: {t2-t1}')
    print(f'Time consumed for using list: {t3-t2}')
    
    # Output
    Time consumed for using range: 2.62e-06
    Time consumed for using list: 0.031
    

    确实,使用range几乎不占用任何时间,而用list则需要占用大量的时间。当然聪明的人一眼能看出,range只是定义了生成逻辑,真正提取数据项的时候还是需要时间的嘛,没错,但是这两个逻辑是不一样的。使用range的时候,我们每生成一项就可以对这个数据进行一些操作,但如果使用list,必须得等整个列表生成完毕才能操作。这就是为什么我们写for循环的时候都是写for i in range(x)的原因了。

    二、yield关键字

    yield关键字用于函数中,将该函数的返回结果变成生成器。看下面例子,给定一个数组x,需要返回一个新数组,其中每一项为原数组的平方:

    # 返回list
    def SquareList(x):
        result = []
        for i in x:
            result.append(i * i)
        return result
    
    # 返回生成器
    def SqaureGen(x):
        for i in x:
            yield i * i
    
    gen = SqaureGen([1,2,3,4])
    for i in gen:
        print(i)
    # Output:
    1
    4
    9
    16
    

    其中SquareGen函数通过yield关键字返回了一个生成器,效果同第一节解释的情况。

    相关文章

      网友评论

        本文标题:Python 生成器以及yield关键字

        本文链接:https://www.haomeiwen.com/subject/ihnbmhtx.html