Python之生成器

本文經過文章同步功能推送至博客園,顯示排版可能會有所錯誤,請見諒!

1、初識生成器

生成器能夠理解一種自動實現迭代器協議的數據類型,因此生成器自己就是一個迭代器 python

區別於列表、元組、字符串等可迭代對象,生成器無需調用__iter__()方法直接就能使用next方法進行迭代 多線程

生成器有兩種定義方法 併發

1.定義一個函數。用yield替代return,調用函數時,當運行到yield時,返回一個值同時函數暫停,直到下一次調用函數,返回下一個yield或Stopitertion錯誤 函數

2.生成器表達式。區別於列表解析式,列表解析式使用[]定義,一經生成,直接讀入內存。而生成器表達式只有在實際調用時纔會讀入內存,使用()定義,優點是內存佔用小,效率高。 高併發

2、生成器優化

生成器相比於列表解析式,有幾個優勢: 測試

1.佔用內存小,幾乎不佔內存 大數據

2.只有在使用next時,纔會返回值 優化

3.next以前的值都會被python刪除(即佔用內存小的緣由) spa

"""使用列表狀況"""
import time
t0 = time.time()
def make_baozi(n):
    """製造n個包子並返回"""
    return ["包子%s" % i for i in range(1,n+1)]
def chi_baozi(*args):
    '''給我多少個包子我就吃多少個'''
    for i,x in enumerate(args):
        print('第%d個客人吃了%s' % (i+1,x))
chi_baozi(*make_baozi(5000000))

全程耗時45.34496521949768秒 線程

此時Python佔用內存高達547M且與生產包子數表現出明顯正相關

'''生成器優化'''
def make_baozi(n):
    for i in range(1,n+1):
        yield '包子%d' %i
def chi_baozi(x):
    print('客人吃了%s' % x)
mb = make_baozi(5000000)
while True:
    try:
        chi_baozi(mb.__next__())
    except StopIteration:
        break

全程耗時47.534424781799316秒

此時Python全程佔用內存6.2M  且內存佔用與生產包子個數不相關

上述代碼爲測試使用列表解析式和生成器表達式的相關佔用區別,能夠看出來,生成器幾乎不佔內存,對於大數據處理內存優化提高十分明顯。在這個模擬程序中,總耗時並沒有顯著區別,主要取決於cpu處理速度。可是對於單個用戶體驗來講,總體有所提高(客人吃到包子1的時間明顯提早了,而吃到最後一個包子時間則相差無幾)。

3、更多

Python因爲全局鎖(GIT)的存在,其併發效率低一直受人詬病,而Python的多線程和多進程也存在很多問題並不是很好的解決方案,Python開發社區逐漸將視野轉到協程上來,經過多線程/多線程再輔以協程能夠提升併發效率,而協程主要基於生成器來實現。關於生成器與協程,請聽下回分解。

相關文章
相關標籤/搜索