日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python查看函数定义_从函数内函数定义看python的函数实现

發布時間:2025/3/19 python 255 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python查看函数定义_从函数内函数定义看python的函数实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、問題

在C/C++中,函數的定義本質上是在編譯階段完成,而函數調用是由鏈接完成。但是對于python這種語言,函數的定義和調用都是由解釋器在運行時完成,或者說,解釋器在執行函數定義的時候,同樣是生成了虛擬機指令,這個指令通常可以理解為MAKE_FUNCTION這個虛擬機指令,這個指令生成的則是一個PyFunctionObject對象。對應的,在函數調用的時候執行的是CALL_FUNCTION,這個指令需要生成一個PyFrameObject對象。

二、CALL_FUNCTION的執行

1、函數的調用

一個函數的構成。靜態代碼信息大致對應函數模版,也就是函數本身的描述信息:例如函數的虛擬機指令集合、使用的常量、使用的自由變量數量、局部變量數量等信息。但是,函數執行時候,最為關鍵的是需要一個棧信息,這個是函數的動態特性。如果一個函數需要在多線程中運行,那么它必須有自己私有的堆棧信息。

可以看到,在執行CALL_FUNCTION指令時,會動態創建一個PyFrameObject對象,這個變量從名字上看就可以知道它對于保存局部變量有著責無旁貸的義務。

static PyObject *

_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,

PyObject **args, Py_ssize_t argcount,

PyObject **kwnames, PyObject **kwargs,

Py_ssize_t kwcount, int kwstep,

PyObject **defs, Py_ssize_t defcount,

PyObject *kwdefs, PyObject *closure,

PyObject *name, PyObject *qualname)

{

……

assert(tstate != NULL);

f = PyFrame_New(tstate, co, globals, locals);

……

}

2、堆棧的生成

那么一個函數運行時堆棧中使用的臨時變量存儲在哪里呢?

在調用PyObject_GC_NewVar的時候,額外要求在PyFrameObject結構之后分配extras個Object對象,這個extras包含了堆棧大小,局部變量、cell變量和free變量,一個函數的運行時信息就存儲在這里,它的基地址由f_localsplus執行。從實現上看,f_localsplus定義為

PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */

它定義在函數的最后,從而對象創建之后,這個變量就自動指向了額外變量

PyFrameObject *

PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,

PyObject *locals)

{

……

Py_ssize_t extras, ncells, nfrees;

ncells = PyTuple_GET_SIZE(code->co_cellvars);

nfrees = PyTuple_GET_SIZE(code->co_freevars);

extras = code->co_stacksize + code->co_nlocals + ncells +

nfrees;

if (free_list == NULL) {

f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type,

extras);

……

f->f_code = code;

extras = code->co_nlocals + ncells + nfrees;

f->f_valuestack = f->f_localsplus + extras;

for (i=0; i

f->f_localsplus[i] = NULL;

f->f_locals = NULL;

f->f_trace = NULL;

f->f_exc_type = f->f_exc_value = f->f_exc_traceback = NULL;

……

}

三、一個推論

既然函數定義也有對應的機器指令,那么如果一個函數中嵌套了另一個函數定義,在執行外層函數的時候,內層函數的定義依然會被執行。并且由于兩次執行的棧幀不同,所以每次執行都會由MAKE_FUNCTION生成新的函數對象。我們可以通過下面的代碼驗證一下,可以看到返回的兩個內部函數定義并不相同,雖然邏輯上看是相同的函數。

tsecer@harry: cat innerdef.py

def outter():

def inner():

print("something")

return inner

inner1 =outter()

inner2 = outter()

print(inner1, inner2)

tsecer@harry: python innerdef.py

(, )

tsecer@harry:

總結

以上是生活随笔為你收集整理的python查看函数定义_从函数内函数定义看python的函数实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。