愛伊米

深入理解Python 5個硬核函式!

今天看到一篇很好的對Python中的eval()、exec()及其相關函式總結的一篇博文,第一時間分享給你。

eval, exec, compile, locals, globals這些函式對於深入理解Python很有必要,希望認真看看。

部落格原文:https://www。cnblogs。com/yyds/p/6276746。html

剛好前些天有人提到eval()與exec()這兩個函式,所以就翻了下Python的文件。這裡就來簡單說一下這兩個函式以及與它們相關的幾個函式,如globals()、locals()和compile():

1。 eval函式

函式的作用:

計算指定表示式的值。也就是說它要執行的Python程式碼只能是單個運算表示式(注意eval不支援任意形式的賦值操作),而不能是複雜的程式碼邏輯,這一點和lambda表示式比較相似。

函式定義:

引數說明:

expression:必選引數,可以是字串,也可以是一個任意的code物件例項(可以透過compile函式建立)。如果它是一個字串,它會被當作一個(使用globals和locals引數作為全域性和本地名稱空間的)Python表示式進行分析和解釋。

globals:可選引數,表示全域性名稱空間(存放全域性變數),如果被提供,則必須是一個字典物件。

locals:可選引數,表示當前區域性名稱空間(存放區域性變數),如果被提供,可以是任何對映物件。如果該引數被忽略,那麼它將會取與globals相同的值。

如果globals與locals都被忽略,那麼它們將取eval()函式被呼叫環境下的全域性名稱空間和區域性名稱空間。

返回值:

如果expression是一個code物件,且建立該code物件時,compile函式的mode引數是‘exec’,那麼eval()函式的返回值是None;

否則,如果expression是一個輸出語句,如print(),則eval()返回結果為None;

否則,expression表示式的結果就是eval()函式的返回值;

例項:

輸出結果:

對輸出結果的解釋:

對於變數a,eval函式的globals和locals引數都被忽略了,因此變數x和變數y都取得的是eval函式被呼叫環境下的作用域中的變數值,即:x = 10, y = 20,a = x + y = 30

對於變數b,eval函式只提供了globals引數而忽略了locals引數,因此locals會取globals引數的值,即:x = 1, y = 2,b = x + y = 3

對於變數c,eval函式的globals引數和locals都被提供了,那麼eval函式會先從全部作用域globals中找到變數x, 從區域性作用域locals中找到變數y,即:x = 1, y = 3, c = x + y = 4

對於變數d,因為print()函式不是一個計算表示式,沒有計算結果,因此返回值為None

2。 exec函式

函式的作用:

動態執行Python程式碼。也就是說exec可以執行復雜的Python程式碼,而不像eval函式那麼樣只能計算一個表示式的值。

函式定義:

引數說明:

object:必選引數,表示需要被指定的Python程式碼。它必須是字串或code物件。如果object是一個字串,該字串會先被解析為一組Python語句,然後在執行(除非發生語法錯誤)。如果object是一個code物件,那麼它只是被簡單的執行。

globals:可選引數,同eval函式

locals:可選引數,同eval函式

返回值:

exec函式的返回值永遠為None。

需要說明的是在Python 2中exec不是函式,而是一個內建語句(statement),但是Python 2中有一個execfile()函式。可以理解為Python 3把exec這個statement和execfile()函式的功能夠整合到一個新的exec()函式中去了:

eval()函式與exec()函式的區別:

eval()函式只能計算單個表示式的值,而exec()函式可以動態執行程式碼段。

eval()函式可以有返回值,而exec()函式返回值永遠為None。

例項1:

我們把例項1中的eval函式換成exec函式試試:

輸出結果:

因為我們說過了,exec函式的返回值永遠為None。

例項2:

輸出結果:

對輸出結果的解釋:

前兩個輸出跟上面解釋的eval函式執行過程一樣,不做過多解釋。關於最後一個數字34,我們可以看出是:x = 1, y = 3是沒有疑問的。關於z為什麼還是30而不是4,這其實也很簡單,我們只需要在理一下程式碼執行過程就可以了,其執行過程相當於:

3。 globals()與locals()函式

函式定義及功能說明:

先來看下這兩個函式的定義和文件描述

描述:

Return a dictionary representing the current global symbol table。 This is always the dictionary of the current module (inside a function or method, this is the module where it is defined, not the module from which it is called)。

翻譯:

返回一個表示當前全域性識別符號表的字典。這永遠是當前模組的字典(在一個函式或方法內部,這是指定義該函式或方法的模組,而不是呼叫該函式或方法的模組)

描述:

Update and return a dictionary representing the current local symbol table。 Free variables are returned by locals() when it is called in function blocks, but not in class blocks。

Note

The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter。

翻譯:

更新並返回一個表示當前區域性識別符號表的字典。自由變數在函式內部被呼叫時,會被locals()函式返回;自由變數在類累不被呼叫時,不會被locals()函式返回。

注意:

locals()返回的字典的內容不應該被改變;如果一定要改變,不應該影響被直譯器使用的區域性變數和自由變數。

總結:

globals()函式以字典的形式返回的定義該函式的模組內的全域性作用域下的所有識別符號(變數、常量等)

locals()函式以字典的形式返回當前函式內的局域作用域下的所有識別符號

如果直接在模組中呼叫globals()和locals()函式,它們的返回值是相同的

例項1:

輸出結果:

例項2:

輸出結果:

上面打印出的G和L的記憶體地址是一樣的,說明在模組級別locals()的返回值和globals()的返回值是相同的。

4。 compile函式

函式的作用:

將source編譯為code物件或AST物件。code物件能夠透過exec()函式來執行或者透過eval()函式進行計算求值。

函式定義:

引數說明:

source:字串或AST(Abstract Syntax Trees)物件,表示需要進行編譯的Python程式碼

filename:指定需要編譯的程式碼檔名稱,如果不是從檔案讀取程式碼則傳遞一些可辨認的值(通常是用‘’)

mode:用於標識必須當做那類程式碼來編譯;如果source是由一個程式碼語句序列組成,則指定mode=‘exec’;如果source是由單個表示式組成,則指定mode=‘eval’;如果source是由一個單獨的互動式語句組成,則指定mode=‘single’。

另外兩個可選引數暫不做介紹

例項:

輸出結果:

5。 這幾個函式的關係

comiple()函式、globals()函式、locals()函式的返回結果可以當作eval()函式與exec()函式的引數使用。

另外,我們可以透過判斷globals()函式的返回值中是否包含某個key來判斷,某個全域性變數是否已經存在(被定義)。