国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

python使用迭代生成器yield減少內(nèi)存占用的方法

這篇具有很好參考價(jià)值的文章主要介紹了python使用迭代生成器yield減少內(nèi)存占用的方法。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

在python編碼中for循環(huán)處理任務(wù)時(shí),會(huì)將所有的待遍歷參量加載到內(nèi)存中。

其實(shí)這本沒有必要,因?yàn)檫@些參量很有可能是一次性使用的,甚至很多場景下這些參量是不需要同時(shí)存儲(chǔ)在內(nèi)存中的,這時(shí)候就會(huì)用到本文所介紹的迭代生成器yield。

1.基本使用

首先我們用一個(gè)例子來演示一下迭代生成器yield的基本使用方法,這個(gè)例子的作用是構(gòu)造一個(gè)函數(shù)用于生成一個(gè)平方數(shù)組02,12,22...。

在普通的場景中我們一般會(huì)直接構(gòu)造一個(gè)空的列表,然后將每一個(gè)計(jì)算結(jié)果填充到列表中,最后return列表即可,對(duì)應(yīng)的是這里的函數(shù)square_number。

而另外一個(gè)函數(shù)square_number_yield則是為了演示yield而構(gòu)造的函數(shù),其使用語法跟return是一樣的,不同的是每次只會(huì)返回一個(gè)值:

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ù)中我們對(duì)比了兩種方法執(zhí)行的結(jié)果,打印在同一行上面,用end=''指令可以替代行末的換行符號(hào),具體執(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é)果是一樣的。也許有些場景下就是需要持久化的存儲(chǔ)函數(shù)中返回的結(jié)果,這一點(diǎn)用yield也是可以實(shí)現(xiàn)的,可以參考如下示例:

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生成的對(duì)象轉(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

2.進(jìn)階測試

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

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)

這個(gè)程序一方面通過time來測試執(zhí)行的時(shí)間,另一方面利用tracemalloc追蹤程序的內(nèi)存變化。

這里是先用np.random.randn()直接產(chǎn)生了100000個(gè)隨機(jī)數(shù)的數(shù)組用于計(jì)算,那么自然在計(jì)算的過程中需要存儲(chǔ)這些生成的隨機(jī)數(shù),就會(huì)占用這么多的內(nèi)存空間。

如果使用yield的方法,每次只產(chǎn)生一個(gè)用于計(jì)算的隨機(jī)數(shù),并且按照上一個(gè)章節(jié)中的用法,這個(gè)迭代生成的隨機(jī)數(shù)也是可以轉(zhuǎn)化為一個(gè)完整的list的:

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)

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

[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),兩種方法的計(jì)算時(shí)間是幾乎差不多的,但是在內(nèi)存占用上yield有著明顯的優(yōu)勢。當(dāng)然,也許這個(gè)例子并不是非常的恰當(dāng),但是本文主要還是介紹yield的使用方法及其應(yīng)用場景。

3.無限長迭代器

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

def get_primes(number):
    while True:
        if is_prime(number):
            yield number

        number += 1

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

def yield_range2(i):
    while True:
        yield i
        i += 2
        
#學(xué)習(xí)中遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流群:153708845 
iter = yield_range2(0)
for i in range(10):

    print (next(iter))

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

[dechin@dechin-manjaro yield]$ python3 yield_iter.py 
0
2
4
6
8
10
12
14
16

18

總結(jié)

本文介紹了python的迭代器yield,其實(shí)關(guān)于yield,我們可以簡單的將其理解為單個(gè)元素的return。

這樣不僅就初步理解了yield的使用語法,也能夠大概了解到y(tǒng)ield的優(yōu)勢,也就是在計(jì)算過程中每次只占用一個(gè)元素的內(nèi)存,而不需要一直存儲(chǔ)大量的元素在內(nèi)存中。文章來源地址http://www.zghlxwxcb.cn/news/detail-861316.html

到了這里,關(guān)于python使用迭代生成器yield減少內(nèi)存占用的方法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 8 python的迭代器和生成器

    概述 ????????在上一節(jié),我們介紹了Python的模塊和包,包括:什么是模塊、導(dǎo)入模塊、自定義模塊、__name__、什么是包、創(chuàng)建包、導(dǎo)入包等內(nèi)容。在這一節(jié)中,我們將介紹Python的迭代器和生成器。在Python中,迭代器是一個(gè)非常重要的概念,它使得我們能夠遍歷一個(gè)序列而無

    2024年02月10日
    瀏覽(17)
  • Python中的迭代器與生成器

    在Python中,迭代器(Iterator)和生成器(Generator)是兩種用于處理可迭代對(duì)象的重要工具。而可迭代對(duì)象包括列表,元組,字典,字符串等。 迭代器和生成器只能迭代一次,通常用于處理大型數(shù)據(jù)集,因?yàn)樗鼈儾粫?huì)一次性加載所有數(shù)據(jù)到內(nèi)存中,而是根據(jù)需要逐個(gè)生成值。

    2024年02月10日
    瀏覽(34)
  • 3.0 Python 迭代器與生成器

    當(dāng)我們需要處理一個(gè)大量的數(shù)據(jù)集合時(shí),一次性將其全部讀入內(nèi)存并處理可能會(huì)導(dǎo)致內(nèi)存溢出。此時(shí),我們可以采用迭代器 Iterator 和生成器 Generator 的方法,逐個(gè)地處理數(shù)據(jù),從而避免內(nèi)存溢出的問題。 迭代器是一個(gè)可以逐個(gè)訪問元素的對(duì)象,它實(shí)現(xiàn)了 python 的迭代協(xié)議,即

    2024年02月13日
    瀏覽(26)
  • Python迭代器與生成器研究記錄

    迭代器肯定是可迭代對(duì)象,但是可迭代對(duì)象不一定是迭代器,生成器一定是迭代器,但是迭代器不一定是生成器 生成器是特殊的迭代器,所以生成器一定是迭代器,迭代器一定是可迭代對(duì)象 我們平常接觸最多的對(duì)象中,字符串,字典,列表,集合,元組和open打開的文件對(duì)象

    2024年02月05日
    瀏覽(17)
  • 【python高級(jí)用法】迭代器、生成器、裝飾器、閉包

    【python高級(jí)用法】迭代器、生成器、裝飾器、閉包

    可迭代對(duì)象:可以使用for循環(huán)來遍歷的,可以使用isinstance()來測試。 迭代器:同時(shí)實(shí)現(xiàn)了__iter__()方法和__next__()方法,可以使用isinstance()方法來測試是否是迭代器對(duì)象 使用類實(shí)現(xiàn)迭代器 兩個(gè)類實(shí)現(xiàn)一個(gè)迭代器 一個(gè)類實(shí)現(xiàn)迭代器 可迭代對(duì)象與迭代器的總結(jié) 一個(gè)具備了__iter_

    2024年02月03日
    瀏覽(24)
  • Python基礎(chǔ)篇(十):迭代器與生成器

    Python基礎(chǔ)篇(十):迭代器與生成器

    迭代器和生成器是Python中用于 處理可迭代對(duì)象 的重要概念。它們提供了一種有效的方式來 遍歷和訪問 集合中的元素,同時(shí)具有 節(jié)省內(nèi)存和惰性計(jì)算 的特點(diǎn)。下面是關(guān)于迭代器和生成器的詳細(xì)介紹和示例: 迭代器是一種實(shí)現(xiàn)了迭代協(xié)議的對(duì)象,它可以用于遍歷集合中的元素

    2024年02月10日
    瀏覽(22)
  • Python教程(26)——Python迭代器和生成器詳解

    Python中的迭代器是一種對(duì)象,它可以迭代(遍歷)一個(gè)可迭代對(duì)象(比如列表、元組或字符串)的元素。迭代器用于實(shí)現(xiàn)迭代器協(xié)議,即包含 __iter__() 方法和 __next__() 方法。 迭代器的工作原理是每次調(diào)用 __next__() 方法時(shí)返回可迭代對(duì)象的下一個(gè)元素,當(dāng)沒有元素可迭代時(shí),拋

    2024年02月19日
    瀏覽(22)
  • Python小姿勢 - ## Python中的迭代器與生成器

    Python小姿勢 - ## Python中的迭代器與生成器

    Python中的迭代器與生成器 在Python中,迭代是一個(gè)非常重要的概念,迭代器和生成器是迭代的兩種最常見的形式。那么,迭代器與生成器有何不同呢? 首先,我們先來了解一下迭代器。 迭代器是一種對(duì)象,它可以記住遍歷的位置,并在每次訪問時(shí)返回下一個(gè)元素。迭代器只能

    2024年02月04日
    瀏覽(29)
  • 【Python 4】列表與元組slice切片 迭代 列表生成式 生成器generator 迭代器Iterator對(duì)象

    在Python中,代碼不是越多越好,而是越少越好 取一個(gè)list或tuple的部分元素是非常常見的操作 對(duì)這種經(jīng)常取指定索引范圍的操作,用循環(huán)十分繁瑣,因此,Python提供了切片(Slice)操作符,能大大簡化這種操作 L[0:3]表示,從索引0開始取,直到索引3為止,但不包括索引3 如果第

    2024年02月07日
    瀏覽(17)
  • Python黑魔法:探秘生成器和迭代器的神奇力量

    在Python中,生成器和迭代器是實(shí)現(xiàn)惰性計(jì)算的兩種重要工具,它們可以幫助我們更有效地處理數(shù)據(jù),特別是在處理大數(shù)據(jù)集時(shí),可以顯著減少內(nèi)存的使用。接下來,我們將詳細(xì)介紹這兩種工具。 迭代器是一種特殊的對(duì)象,它可以遍歷一個(gè)集合中的所有元素。任何實(shí)現(xiàn)了__ite

    2024年02月12日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包