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

歡迎訪問 生活随笔!

生活随笔

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

python

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

發布時間:2025/3/19 python 171 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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的函数实现的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 天天干天天舔天天射 | 亚洲区一区二区 | 中文字幕高清在线观看 | 草逼视频网站 | 国产一级在线视频 | 色人综合 | 日韩国产在线一区 | 96精品| 美女mm131爽爽爽免费动视频 | 欧美二三区 | 国产成人精品久久二区二区91 | 欧美r级在线观看 | 亚洲欧美高清视频 | 国产av第一区 | 亚洲精品久久久久av无码 | 天天射天天舔 | 97色伦97色伦国产欧美空 | 四虎影视成人永久免费观看亚洲欧美 | 99视频在线精品免费观看2 | 麻豆最新网址 | 精品一区二区三区免费毛片 | 日韩少妇内射免费播放18禁裸乳 | 欧美成人一区二区三区高清 | 色图在线观看 | 国产精品中文在线 | 欧美亚洲视频一区 | 日韩久久精品一区二区 | 一级a毛片免费观看久久精品 | a色视频| 国产精品久久 | 国产精品九 | 国产一区二区在线精品 | 欧美亚洲一区二区三区 | 成人欧美一区二区三区黑人 | 日韩高清网站 | 女仆乖h调教跪趴1v1 | 久久国产经典视频 | 91porny九色 | 自拍偷拍国产精品 | 国产精品资源在线 | 青青导航| 亚洲男人在线 | 欧美伦理一区二区 | 麻豆系列在线观看 | 国产第一毛片 | 久久神马影院 | 欧美日韩亚洲国产 | 国产内谢| 亚洲小视频在线观看 | 欧美一区二区视频免费观看 | 欧美爱爱网站 | 日本v视频 | 国产三区视频 | 天天操天天干天天舔 | www.黄色大片 | 久久久视| xxxx日本高清 | 女仆乖h调教跪趴1v1 | 国产在线观看精品 | 亚洲欧美在线视频免费 | 欧美啪啪一区 | 亚洲成a人v欧美综合天堂麻豆 | 亚洲高清自拍 | 男女激情视频网站 | 亚洲伦理影院 | 又黄又爽一区二区三区 | 日韩三级一区 | 中文文字幕文字幕高清 | 在线免费你懂的 | 一卡二卡三卡四卡五卡 | 欧美一区二区三区电影 | 特黄av| 中国农村一级片 | 中文字幕一区二区三区四区免费看 | 在线观看亚洲色图 | 黄色工厂这里只有精品 | 国产精品一二三四五区 | 国产老头老太作爱视频 | 在线免费看毛片 | 关秀媚三级 | www.久久久久久久久 | 午夜影院美女 | 日日夜夜综合 | 毛片在哪看 | 亚洲不卡中文字幕 | 成人免费视频国产免费 | 99re8在线精品视频免费播放 | 日韩一区二区在线观看视频 | 激情综合影院 | 午夜三级福利 | 欧美精品一区二区性色a+v | 欧美群交射精内射颜射潮喷 | 日本黄色小片 | 日本强好片久久久久久aaa | 欧洲精品码一区二区三区免费看 | youjizz韩国 | 欧美一区二区三区爽爽爽 | a三级黄色片 | 精品视频一区二区 |