python exec 和 eval 函式的用法

2021-08-02 02:22:15 字數 3209 閱讀 9719

在網上看到關於python exec和eval函式 的用法,寫的很深刻,記錄如下 。

python有時需要動態的創造python**,然後將其作為語句執行  或  作為表示式計算。

exec用於執行儲存在字串中的python**。

1、 語句與表示式的區別:表示式是 某事,語句是 做某事(即告訴計算機做什麼)。

比如2*2是4,而print 2*2是列印4。上述兩句**在互動式直譯器中執行的結果是一樣的,是因為直譯器總是把所有表示式的值列印出來而已。而在程式中編寫類似2*2這樣的表示式並不會列印顯示什麼,編寫print 2*2則會列印4。

語句與表示式的區別在賦值時更明顯,因為語句不是表示式,所以沒有值。如在互動式直譯器中輸入 x=2則不會列印任何東西,立刻出現新的提示符。雖然什麼也沒顯現,但是有些東西已經發生變化如x的值現在變為3.這也是語句特性的一般定義:它們改變了事物。比如,賦值語句改變了變數,print語句改變了螢幕顯示的內容。

2、 命名空間(作用域) 全域性變數和區域性變數

除了全域性作用域外,每個函式會都會建立乙個新的作用域。變數分為全域性變數和區域性變數,函式內的變數稱為區域性變數只在區域性命名空間中起作用。

在函式內部讀取全域性變數一般來說不是問題,直接訪問即可。但是,如果區域性變數名或者引數的名字與全域性變數名相同的話,就不能直接訪問了,因為全域性變數被區域性變數給遮蔽了。如果確實需要的話,可以使用globals函式獲取被遮蔽的全域性變數值。(globals返回全域性變數的字典,locals返回區域性變數的值)。例如:有乙個名為parameter的全域性變數,那麼在combine(parameter)函式內部訪問全域性變數時,因為與引數重名,必須使用globals()['parameter']獲取。**如下:

def combine(parameter):

print parameter+globals()['parameter']

#函式呼叫

parameter="hello"

combine("berry")

上面講的是再函式內部讀取全域性變數的方法,不包括修改。如果要在函式內部修改全域性變數,需要告知修改的值是全域性變數,因為在函式內部將值賦予乙個變數那麼變數自動成為區域性變數。通過global關鍵字來告訴python函式內乙個需要修改的變數是乙個全域性變數。**如下:

x=1

def inc_x():

global x

x=x+1

eval("inc_x()")

print x

3、執行字串的語句  exec

如輸入exec "print  'hello'"會列印出hello。(注意:python 3.0中,exec是乙個函式不是乙個語句了,因此使用exec('字串語句')的方式來呼叫)。exec執行字串語句存在安全風險,因為exec可能會干擾命名空間,即改變不應該變的變數。例如:

從上面的例子可以看出,exec干擾了命名空間,改變了sqrt的值,使其不是乙個函式而變成1了。由此可見,如果對exec不加限制就會存在安全風險。下面是改進措施。

措施:通過增加 in 來實現,其中的是乙個字典,該字典起到放置**字串命名空間的作用。這樣exec執行的**只會在代表的命名空間中起作用。如:

從上面**中可以看到,exec語句在scope命名空間中執行,不會影響到現在命名空間的sqrt。scope雖然充當命名空間的作用,但實質仍是乙個字典,所以如果想知道scope命名空間中有多少變數時,可通過len(scope)獲得,可通過scope.key()獲得scope命名空間的所有變數。

4、eval 會計算字串形式的python表示式,並返回結果的值。

exec語句不會返回任何物件。而eval會返回表示式的值。下面的**可以建立乙個python計算器:

#python計算器

print

eval

(raw_input(

"please input an arithmetic expression:"))

上面**解釋,上面**中eval內部現在還不是字串,首先執行raw_input()函式,raw_input()返回你輸入的求值字串,現在eval函式內部就是求值字串了,就可以用eval進行字串的求值了。如輸入:4*5+6,那麼raw_input就會返回「4*5+6」,eval求值後為26.

要注意上面**與下面**的區別:

print eval('raw_input("please input an arithmetic expression:")')
在這個**中,與python計算器**不同的是,eval函式內直接就是字串,那麼直接對字串求值,但是字串中是raw_input表示式,raw_input表示式將使用者的輸入轉換為字串,所以如果輸入4+5的話會返回"4+5"。注意:raw_input('***xx')是乙個表示式,表示式的值就是使用者輸入。  可能疑惑的是**:exec('raw_input("please input an arithmetic expression:")')不會報錯,因為ecec也可以用於表示式,只是什麼效果也沒達到而已(既不返回值,也沒乾事情)。

跟exec一樣,eval也可以使用命名空間。因為儘管表示式一般不會給變數重新賦值,但是表示式可以通過呼叫函式來達到給全域性變數賦值的目的。例如執行下面**後,全域性變數x的值會被重新賦值為2:

x=1

def inc_x():

global x

x=x+1

eval("inc_x()")

print x

從上面的**可以看出eval函式也是不安全的,必須使用命名空間。事實上,可以為eval提供兩個命名空間,乙個是全域性的,另乙個是區域性的。全域性的必須是字典,區域性的可以是任何形式的對映。

exec和eval的命名空間使用**(命名空間可以不是空的字典,可以提前為命名空間提供一些值):

scope={}

scope['x']=1

scope['y']=2

print eval('x+y',scope)

scope={}

exec "x=2" in scope

eval("x*x",scope

Python exec 內建語句

exec 執行儲存在字串或檔案中的 python 語句,相比於 eval,exec可以執行更複雜的 python 以下是 exec 的語法 exec object globals locals exec 返回值永遠為 none。以下展示了使用 exec 的例項 exec print hello wo...

Python exec 內建語句

exec 執行儲存在字串或檔案中的python語句,相比於 eval,exec可以執行更複雜的 python 需要說明的是在 python2 中exec不是函式,而是乙個內建語句 statement 但是python 2中有乙個 execfile 函式。可以理解為 python 3 把 exec 這...

執行順序和eval

1 將命令切割成token 是以固定的一支煙meta字元分割的,有空格 製表符 換行符 與 token 的種類暴扣單詞,關鍵字 輸出入重定向 以及分號 2 檢查每個命令的第乙個token,看看是否他是不帶引號或者反斜槓的關鍵字,如果他是乙個開發的關鍵字,則這個命令其實是乙個復合命令 3 將每個命令的...