玩轉python(5)生成器的原理

2022-09-13 11:45:11 字數 1259 閱讀 1270

函式的呼叫滿足「後進先出」的原則,也就是說,最後被呼叫的函式應該第乙個返回,函式的遞迴呼叫就是乙個經典的例子。顯然,記憶體中以「後進先出」方式處理資料的棧段是最適合用於實現函式呼叫的載體,在編譯型程式語言中,函式被呼叫後,函式的引數,返回位址,暫存器值等資料會被壓入棧,待函式體執行完畢,將上述資料彈出棧。這也意味著,乙個被呼叫的函式一旦執行完畢,它的生命週期就結束了。

在python這樣的解釋型語言中,函式的呼叫也是依賴棧的。之前說過,python的標準直譯器是用c寫的。直譯器用乙個叫做pyeval_evalframeex的c函式來執行python程式。對於乙個python中的函式,直譯器接受乙個python的棧幀物件,並在這個棧幀的上下文中執行python位元組碼。

我們來看看這樣乙個例子:

import dis

def foo():

bar()

def bar():

pass

print(dis.dis(foo))

我們用dis模組可以檢視python程式的位元組碼,下面是函式foo()的位元組碼:

0 load_global              0 (bar)

2 call_function 0

4 pop_top

6 load_const 0 (none)

8 return_value

foo函式將bar載入到棧中並呼叫它,然後從棧中彈出返回值,最後載入並返回none,當pyeval_evalframeex遇到call_function位元組碼的時候,它會建立乙個新的python棧幀,然後用這個新的幀作為引數遞迴呼叫pyeval_evalframeex來執行bar。不過有一點要注意的是,python直譯器是個普通的c程式,所以它的堆疊幀就是普通的堆疊。但是它操作的python堆疊幀是分配在堆上的,所以python的棧幀可以在它的呼叫之外存活。而且可以顯式的儲存下來。

這是python生成器的技術基礎,下面是乙個生成器:

def gen():

yield 1

yield 2

g = gen()

next(g)

print(type(g))

返回的結果是:

呼叫gen()產生的所有生成器都指向同乙個**物件,但是每個都有自己的堆疊幀。這個堆疊幀並不存在於實際的堆疊上,它在堆記憶體上等待著被使用。

python3生成器 Python3 生成器

python3 生成器 閱讀 125 發布於 2020 05 19 14 29 25 在python中,一邊迴圈一邊計算出元素的機制,稱為生成器 generator。生成器的優點 一次返回乙個結果,延遲計算。這對於大資料量處理,是個非常有用的優勢。占用記憶體量是工程師必須考慮的乙個問題。提高 可讀性...

Python(九)生成器

該系列文章用來記錄一下自己在b站學習python時,進行上機練習用的 使用 pycharm 2020.3.3 慕課 python語言基礎與應用 北京大學 陳斌 字幕校對 編寫程式,輸入兩個數,輸出它們的商,採用例外處理來處理兩種錯誤,給出使用者友好的提示資訊 1 除數為0 2 輸入了非數值 try ...

Python筆記003 生成器和生成器表示式

以下是我學習 流暢的python 後的個人筆記,現在拿出來和大家共享,希望能幫到各位python學習者。生成器使用yield做關鍵字,一次只返回乙個值給呼叫者,然後暫停執行,其作用是 節省記憶體空間。生成器可以用next 函式,也可以用for迭代的方式獲取元素值,中間還可以用close 來隨時終止生...