真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

python傳遞函數(shù)原理 python函數(shù)值傳遞和引用傳遞

python程序如何工作

隨著人工智能時代的來臨,python成為了人們學(xué)習(xí)編程的首先語言。那么,python程序怎么運(yùn)行的?我們下面來介紹下。

創(chuàng)新互聯(lián)專注于成都做網(wǎng)站、網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計、網(wǎng)站制作、網(wǎng)站開發(fā)。公司秉持“客戶至上,用心服務(wù)”的宗旨,從客戶的利益和觀點(diǎn)出發(fā),讓客戶在網(wǎng)絡(luò)營銷中找到自己的駐足之地。尊重和關(guān)懷每一位客戶,用嚴(yán)謹(jǐn)?shù)膽B(tài)度對待客戶,用專業(yè)的服務(wù)創(chuàng)造價值,成為客戶值得信賴的朋友,為客戶解除后顧之憂。

python程序執(zhí)行原理

我們都知道,使用C,C++之類的編譯性語言編寫的程序,是需要從源文件轉(zhuǎn)換成計算機(jī)使用的機(jī)器語言,經(jīng)過鏈接器鏈接之后形成了二進(jìn)制可執(zhí)行文件。運(yùn)行該程序的時候,就可以二進(jìn)制程序從硬盤載入到內(nèi)存中并運(yùn)行。

相關(guān)推薦:《Python教程》

但是對于Python而言,Python源碼不需要編譯成二進(jìn)制代碼,它可以直接從源代碼運(yùn)行程序。Python解釋器將源代碼轉(zhuǎn)換為字節(jié)碼,然后把編譯好的字節(jié)碼轉(zhuǎn)發(fā)到Python虛擬機(jī)(PVM)中進(jìn)行執(zhí)行。當(dāng)我們運(yùn)行Python程序的時候,Python解釋器會執(zhí)行兩個步驟。

(1) 把源代碼編譯成字節(jié)碼。編譯后的字節(jié)碼是特定于Python的一種表現(xiàn)形式,它不是二進(jìn)制的機(jī)器碼,需要進(jìn)一步編譯才能被機(jī)器執(zhí)行,這也是Python代碼無法運(yùn)行的像C,C++一樣快的原因。如果Python進(jìn)程在機(jī)器上擁有寫入權(quán)限,那么它將把程序的字節(jié)碼保存為一個以.pyc為擴(kuò)展名的文件,如果Python無法在機(jī)器上寫入字節(jié)碼,那么宇節(jié)碼將會在內(nèi)存中生成并在程序結(jié)束時自動丟棄。在構(gòu)建程序的時候最好給Python賦上在計算機(jī)上寫的權(quán)限,這樣只要源代碼沒有改變,生成的.pyc文件可以重復(fù)利用,提高執(zhí)行效率。

(2) 把編譯好的字節(jié)碼轉(zhuǎn)發(fā)到Python虛擬機(jī)(PVM)中進(jìn)行執(zhí)行。PVM是Python Virtual Machine的簡稱,它是Python的運(yùn)行引擎,是Python系統(tǒng)的一部分,它是迭代運(yùn)行字節(jié)碼指令的一個大循環(huán),一個接一個地完成操作。

ue5python原理

Python先把代碼(.py文件)編譯成字節(jié)碼,交給字節(jié)碼虛擬機(jī),然后解釋器一條一條執(zhí)行字節(jié)碼指令,從而完成程序的執(zhí)行。

1.1python先把代碼(.py文件)編譯成字節(jié)碼,交給字節(jié)碼虛擬機(jī),然后解釋器會從編譯得到的PyCodeObject對象中一條一條執(zhí)行字節(jié)碼指令,

并在當(dāng)前的上下文環(huán)境中執(zhí)行這條字節(jié)碼指令,從而完成程序的執(zhí)行。Python解釋器實際上是在模擬操作中執(zhí)行文件的過程。PyCodeObject對象

中包含了字節(jié)碼指令以及程序的所有靜態(tài)信息,但沒有包含程序運(yùn)行時的動態(tài)信息——執(zhí)行環(huán)境(PyFrameObject)

2. 字節(jié)碼

字節(jié)碼在python解釋器程序里對應(yīng)的是PyCodeObject對象

.pyc文件是字節(jié)碼在磁盤上的表現(xiàn)形式

2.1從整體上看:OS中執(zhí)行程序離不開兩個概念:進(jìn)程和線程。python中模擬了這兩個概念,模擬進(jìn)程和線程的分別是PyInterpreterState和

PyTreadState。即:每個PyThreadState都對應(yīng)著一個幀棧,python解釋器在多個線程上切換。當(dāng)python解釋器開始執(zhí)行時,它會先進(jìn)行一

些初始化操作,最后進(jìn)入PyEval_EvalFramEx函數(shù),它的作用是不斷讀取編譯好的字節(jié)碼,并一條一條執(zhí)行,類似CPU執(zhí)行指令的過程。函數(shù)內(nèi)部

主要是一個switch結(jié)構(gòu),根據(jù)字節(jié)碼的不同執(zhí)行不同的代碼。

3. .pyc文件

PyCodeObject對象的創(chuàng)建時機(jī)是模塊加載的時候,及import

Python test.py會對test.py進(jìn)行編譯成字節(jié)碼并解釋執(zhí)行,但是不會生成test.pyc

如果test.py加載了其他模塊,如import urlib2, Python會對urlib2.py進(jìn)行編譯成字節(jié)碼,生成urlib2.pyc,然后對字節(jié)碼進(jìn)行解釋

如果想生成test.pyc,我們可以使用Python內(nèi)置模塊py_compile來編譯。

加載模塊時,如果同時存在.py和pyc,Python會嘗試使用.pyc,如果.pyc的編譯時間早于.py的修改時間,則重新編譯.py并更新.pyc。

4. PyCodeObject

Python代碼的編譯結(jié)果就是PyCodeObject對象

typedef struct {

PyObject_HEAD

int co_argcount; /* 位置參數(shù)個數(shù) */

int co_nlocals; /* 局部變量個數(shù) */

int co_stacksize; /* 棧大小 */

int co_flags;

PyObject *co_code; /* 字節(jié)碼指令序列 */

PyObject *co_consts; /* 所有常量集合 */

PyObject *co_names; /* 所有符號名稱集合 */

PyObject *co_varnames; /* 局部變量名稱集合 */

PyObject *co_freevars; /* 閉包用的的變量名集合 */

PyObject *co_cellvars; /* 內(nèi)部嵌套函數(shù)引用的變量名集合 */

/* The rest doesn’t count for hash/cmp */

PyObject *co_filename; /* 代碼所在文件名 */

PyObject *co_name; /* 模塊名|函數(shù)名|類名 */

int co_firstlineno; /* 代碼塊在文件中的起始行號 */

PyObject *co_lnotab; /* 字節(jié)碼指令和行號的對應(yīng)關(guān)系 */

void *co_zombieframe; /* for optimization only (see frameobject.c) */

} PyCodeObject;

5. .pyc文件格式

加載模塊時,模塊對應(yīng)的PyCodeObject對象被寫入.pyc文件

6.分析字節(jié)碼

6.1解析PyCodeObject

Python提供了內(nèi)置函數(shù)compile可以編譯python代碼和查看PyCodeObject對象

6.2指令序列co_code的格式

opcode oparg opcode opcode oparg …

1 byte 2 bytes 1 byte 1 byte 2 bytes

Python內(nèi)置的dis模塊可以解析co_code

7. 執(zhí)行字節(jié)碼

Python解釋器的原理就是模擬可執(zhí)行程序再X86機(jī)器上的運(yùn)行,X86的運(yùn)行時棧幀如下圖

Python解釋器的原理就是模擬上述行為。當(dāng)發(fā)生函數(shù)調(diào)用時,創(chuàng)建新的棧幀,對應(yīng)Python的實現(xiàn)就是PyFrameObject對象。

PyFrameObject對象創(chuàng)建程序運(yùn)行時的動態(tài)信息,即執(zhí)行環(huán)境

7.1 PyFrameObject

typedef struct _frame{

PyObject_VAR_HEAD //"運(yùn)行時棧"的大小是不確定的

struct _frame *f_back; //執(zhí)行環(huán)境鏈上的前一個frame,很多個PyFrameObject連接起來形成執(zhí)行環(huán)境鏈表

PyCodeObject *f_code; //PyCodeObject 對象,這個frame就是這個PyCodeObject對象的上下文環(huán)境

PyObject *f_builtins; //builtin名字空間

PyObject *f_globals; //global名字空間

PyObject *f_locals; //local名字空間

PyObject **f_valuestack; //"運(yùn)行時棧"的棧底位置

PyObject **f_stacktop; //"運(yùn)行時棧"的棧頂位置

//...

int f_lasti; //上一條字節(jié)碼指令在f_code中的偏移位置

int f_lineno; //當(dāng)前字節(jié)碼對應(yīng)的源代碼行

//...

//動態(tài)內(nèi)存,維護(hù)(局部變量+cell對象集合+free對象集合+運(yùn)行時棧)所需要的空間

PyObject *f_localsplus[1];

} PyFrameObject;

每一個 PyFrameObject對象都維護(hù)了一個 PyCodeObject對象,這表明每一個 PyFrameObject中的動態(tài)內(nèi)存空間對象都和源代碼中的一段Code相對應(yīng)。

Python中函數(shù)參數(shù)傳遞問題

對于可變參數(shù)默認(rèn)是引用傳值, 但是不能去修改它的指向, 一旦修改就是按值傳遞.

#?coding=utf-8

def?f(a):

a?=?[0]

print(a)

if?__name__?==?'__main__':

a?=?[1,?2,?3]

f(a)

print(a)

上面的代碼對a重新賦值, 試圖改變a的指向, 那么這時的a就是一個新的局部變量, 而非全局變量a

像a[0] = 100, a.append(0)的操作不會觸發(fā)上述規(guī)則, 和你的輸出一樣


當(dāng)前標(biāo)題:python傳遞函數(shù)原理 python函數(shù)值傳遞和引用傳遞
文章出自:http://weahome.cn/article/docopjj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部