最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python3使用迭代生成器實(shí)現(xiàn)減少內(nèi)存占用

 更新時間:2021年05月05日 10:00:02   作者:DechinPhy  
這篇文章主要介紹了python3使用迭代生成器實(shí)現(xiàn)減少內(nèi)存占用的相關(guān)資料,需要的朋友可以參考下

技術(shù)背景

在python編碼中for循環(huán)處理任務(wù)時,會將所有的待遍歷參量加載到內(nèi)存中。其實(shí)這本沒有必要,因?yàn)檫@些參量很有可能是一次性使用的,甚至很多場景下這些參量是不需要同時存儲在內(nèi)存中的,這時候就會用到本文所介紹的迭代生成器yield。

基本使用

首先我們用一個例子來演示一下迭代生成器yield的基本使用方法,這個例子的作用是構(gòu)造一個函數(shù)用于生成一個平方數(shù)組。在普通的場景中我們一般會直接構(gòu)造一個空的列表,然后將每一個計算結(jié)果填充到列表中,最后return列表即可,對應(yīng)的是這里的函數(shù)square_number。而另外一個函數(shù)square_number_yield則是為了演示yield而構(gòu)造的函數(shù),其使用語法跟return是一樣的,不同的是每次只會返回一個值:

# test_yield.py

def square_number(length):
    s = []
    for i in range(length):
        s.append(i ** 2)
    return s

def square_number_yield(length):
    for i in range(length):
        yield i ** 2

if __name__ == '__main__':
    length = 10
    sn1 = square_number(length)
    sn2 = square_number_yield(length)
    for i in range(length):
        print (sn1[i], '\t', end='')
        print (next(sn2))

在main函數(shù)中我們對比了兩種方法執(zhí)行的結(jié)果,打印在同一行上面,用end=''指令可以替代行末的換行符號,具體執(zhí)行的結(jié)果如下所示:

[dechin@dechin-manjaro yield]$ python3 test_yield.py 
0       0
1       1
4       4
9       9
16      16
25      25
36      36
49      49
64      64
81      81

可以看到兩種方法打印出來的結(jié)果是一樣的。也許有些場景下就是需要持久化的存儲函數(shù)中返回的結(jié)果,這一點(diǎn)用yield也是可以實(shí)現(xiàn)的,可以參考如下示例:

# test_yield.py

def square_number(length):
    s = []
    for i in range(length):
        s.append(i ** 2)
    return s

def square_number_yield(length):
    for i in range(length):
        yield i ** 2

if __name__ == '__main__':
    length = 10
    sn1 = square_number(length)
    sn2 = square_number_yield(length)
    sn3 = list(square_number_yield(length))
    for i in range(length):
        print (sn1[i], '\t', end='')
        print (next(sn2), '\t', end='')
        print (sn3[i])

這里使用的方法是直接將yield生成的對象轉(zhuǎn)化成list格式,或者用sn3 = [i for i in square_number_yield(length)]這種寫法也是可以的,在性能上應(yīng)該差異不大。上述代碼的執(zhí)行結(jié)果如下:

[dechin@dechin-manjaro yield]$ python3 test_yield.py 
0       0       0
1       1       1
4       4       4
9       9       9
16      16      16
25      25      25
36      36      36
49      49      49
64      64      64
81      81      81

進(jìn)階測試

在前面的章節(jié)中我們提到,使用yield可以節(jié)省程序的內(nèi)存占用,這里我們來測試一個100000大小的隨機(jī)數(shù)組的平方和計算。如果使用正常的邏輯,那么寫出來的程序就是如下所示(關(guān)于python內(nèi)存占用的追蹤方法,可以參考這一篇博客):

# square_sum.py

import tracemalloc
import time
import numpy as np
tracemalloc.start()

start_time = time.time()
ss_list = np.random.randn(100000)
s = 0
for ss in ss_list:
    s += ss ** 2
end_time = time.time()
print ('Time cost is: {}s'.format(end_time - start_time))

snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')

for stat in top_stats[:5]:
    print (stat)

這個程序一方面通過time來測試執(zhí)行的時間,另一方面利用tracemalloc追蹤程序的內(nèi)存變化。這里是先用np.random.randn()直接產(chǎn)生了100000個隨機(jī)數(shù)的數(shù)組用于計算,那么自然在計算的過程中需要存儲這些生成的隨機(jī)數(shù),就會占用這么多的內(nèi)存空間。如果使用yield的方法,每次只產(chǎn)生一個用于計算的隨機(jī)數(shù),并且按照上一個章節(jié)中的用法,這個迭代生成的隨機(jī)數(shù)也是可以轉(zhuǎn)化為一個完整的list的:

# yield_square_sum.py

import tracemalloc
import time
import numpy as np
tracemalloc.start()

start_time = time.time()
def ss_list(length):
    for i in range(length):
        yield np.random.random()

s = 0
ss = ss_list(100000)
for i in range(100000):
    s += next(ss) ** 2
end_time = time.time()
print ('Time cost is: {}s'.format(end_time - start_time))

snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')

for stat in top_stats[:5]:
    print (stat)

這兩個示例的執(zhí)行結(jié)果如下,可以放在一起進(jìn)行對比:

[dechin@dechin-manjaro yield]$ python3 square_sum.py 
Time cost is: 0.24723434448242188s
square_sum.py:9: size=781 KiB, count=2, average=391 KiB
square_sum.py:12: size=24 B, count=1, average=24 B
square_sum.py:11: size=24 B, count=1, average=24 B
[dechin@dechin-manjaro yield]$ python3 yield_square_sum.py 
Time cost is: 0.23023390769958496s
yield_square_sum.py:9: size=136 B, count=1, average=136 B
yield_square_sum.py:14: size=112 B, count=1, average=112 B
yield_square_sum.py:11: size=79 B, count=2, average=40 B
yield_square_sum.py:10: size=76 B, count=2, average=38 B
yield_square_sum.py:15: size=28 B, count=1, average=28 B

經(jīng)過比較我們發(fā)現(xiàn),兩種方法的計算時間是幾乎差不多的,但是在內(nèi)存占用上yield有著明顯的優(yōu)勢。當(dāng)然,也許這個例子并不是非常的恰當(dāng),但是本文主要還是介紹yield的使用方法及其應(yīng)用場景。

無限長迭代器

在參考鏈接1中提到了一種用法是無限長的迭代器,比如按順序返回所有的素數(shù),那么此時我們?nèi)绻胷eturn來返回所有的元素并存儲到一個列表里面,就是一個非常不經(jīng)濟(jì)的辦法,所以可以使用yield來迭代生成,參考鏈接1中的源代碼如下所示:

def get_primes(number):
    while True:
        if is_prime(number):
            yield number
        number += 1

那么類似的,這里我們用while True可以展示一個簡單的案例——返回所有的偶數(shù):

# yield_iter.py

def yield_range2(i):
    while True:
        yield i
        i += 2

iter = yield_range2(0)
for i in range(10):
    print (next(iter))

因?yàn)檫@里我們限制了長度是10,所以最終會返回10個偶數(shù):

[dechin@dechin-manjaro yield]$ python3 yield_iter.py

總結(jié)概要

本文介紹了python的迭代器yield,其實(shí)關(guān)于yield,我們可以簡單的將其理解為單個元素的return。這樣不僅就初步理解了yield的使用語法,也能夠大概了解到y(tǒng)ield的優(yōu)勢,也就是在計算過程中每次只占用一個元素的內(nèi)存,而不需要一直存儲大量的元素在內(nèi)存中。

到此這篇關(guān)于python3使用迭代生成器實(shí)現(xiàn)減少內(nèi)存占用的文章就介紹到這了,更多相關(guān)python3實(shí)現(xiàn)減少內(nèi)存占用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • django使用xlwt導(dǎo)出excel文件實(shí)例代碼

    django使用xlwt導(dǎo)出excel文件實(shí)例代碼

    這篇文章主要介紹了django使用xlwt導(dǎo)出excel文件實(shí)例代碼,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • 實(shí)例解析Python設(shè)計模式編程之橋接模式的運(yùn)用

    實(shí)例解析Python設(shè)計模式編程之橋接模式的運(yùn)用

    這篇文章主要介紹了Python設(shè)計模式編程之橋接模式的運(yùn)用,橋接模式主張把抽象部分與它的實(shí)現(xiàn)部分分離,需要的朋友可以參考下
    2016-03-03
  • Python基于list的append和pop方法實(shí)現(xiàn)堆棧與隊列功能示例

    Python基于list的append和pop方法實(shí)現(xiàn)堆棧與隊列功能示例

    這篇文章主要介紹了Python基于list的append和pop方法實(shí)現(xiàn)堆棧與隊列功能,結(jié)合實(shí)例形式分析了Python使用list定義及使用隊列的相關(guān)操作技巧,需要的朋友可以參考下
    2017-07-07
  • 詳解Python使用Plotly繪圖工具,繪制甘特圖

    詳解Python使用Plotly繪圖工具,繪制甘特圖

    這篇文章主要介紹了Python使用Plotly繪圖工具,繪制甘特圖,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • python實(shí)現(xiàn)釘釘機(jī)器人自動打卡天天早下班

    python實(shí)現(xiàn)釘釘機(jī)器人自動打卡天天早下班

    這篇文章主要為大家介紹了python實(shí)現(xiàn)釘釘機(jī)器人自動打卡天天下早班實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • python實(shí)現(xiàn)盲盒抽獎功能(減庫存)

    python實(shí)現(xiàn)盲盒抽獎功能(減庫存)

    本文主要介紹了python實(shí)現(xiàn)盲盒抽獎功能,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Python爬蟲基于lxml解決數(shù)據(jù)編碼亂碼問題

    Python爬蟲基于lxml解決數(shù)據(jù)編碼亂碼問題

    這篇文章主要介紹了Python爬蟲基于lxml解決數(shù)據(jù)編碼亂碼問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • django 刪除數(shù)據(jù)庫表后重新同步的方法

    django 刪除數(shù)據(jù)庫表后重新同步的方法

    今天小編就為大家分享一篇django 刪除數(shù)據(jù)庫表后重新同步的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • Python的強(qiáng)大HTTP庫Requests基本使用

    Python的強(qiáng)大HTTP庫Requests基本使用

    這篇文章主要為大家介紹了Python的強(qiáng)大HTTP庫Requests基本使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • 一文帶你深入理解Python魔法方法

    一文帶你深入理解Python魔法方法

    在Python中,魔法方法是指那些以雙下劃線開頭和結(jié)尾的特殊方法,它們是Python的內(nèi)置方法,對應(yīng)于Python對象的各種運(yùn)算符,這篇文章將深入探討Python的一些魔法方法,并通過示例展示如何使用它們,需要的朋友可以參考下
    2023-06-06

最新評論

图片| 汨罗市| 乡宁县| 巍山| 收藏| 东兰县| 泰和县| 沧源| 石楼县| 扶沟县| 龙胜| 长沙市| 收藏| 丰城市| 哈尔滨市| 榕江县| 德庆县| 灵宝市| 新竹县| 汾西县| 兴安盟| 东方市| 巍山| 潼关县| 水富县| 自贡市| 新沂市| 大名县| 绿春县| 水城县| 江北区| 和平县| 东山县| 儋州市| 延长县| 石门县| 登封市| 那坡县| 阳高县| 鸡西市| 闻喜县|