如何在Python中使用eval ?

2021-03-02 Python頭條

Python中的 eval是什麼?

在Python中,我們有許多內置方法,這些方法對於使Python成為所有人的便捷語言至關重要,而eval是其中一種。eval函數的語法如下:

eval(expression, globals, locals)

如上所示,eval函數採用三個參數:

expression –需要一個字符串,該字符串將被解析並評估為Python表達式globals(可選)–一個字典,用於指定可用的全局方法和變量。locals(可選)-另一個字典,用於指定可用的本地方法和變量。稍後將在本文中顯示對global(全局變量)s和locals(本地變量)的使用。eval在Python中做什麼?

eval函數解析expression參數並將其評估為python表達式。換句話說,我們可以說這個函數解析了傳遞給它的表達式並在程序中運行python expression(code)。

為了評估基於字符串的表達式,Python的eval函數運行以下步驟:

解析表達式

編譯成字節碼

將其評估為Python表達式

返回評估結果

這意味著當我們將任何python表達式作為「字符串」傳遞給eval函數時,它會評估該表達式並將結果返回為整數或浮點數。以下是一些簡單的示例,它們將使您更加清楚。

這是在Python中使用eval將字符串轉換為整數,複數或浮點數的簡單方法:

<code> num =「 23」 float_num =「 53.332」 complex_num =「 2 + 3j」 str1 =「 Not number」 print(eval(num),type(eval(num)))print(eval(float_num),type( eval(float_num)))print(eval(complex_num),type(eval(complex_num)))print(eval(str1),type(eval(str1)))</ code>

OUTPUT: 23                                                                                                                53.332                                                                                                          (2+3j)                                                                                                        Traceback (most recent call last):                                                                                               File "main.py", line 8, in                                                                                               print(eval(str1),type(eval(str1)))                                                                                           File "", line 1                                                                                                          Not number                                                                                                                              ^                                                                                                                 SyntaxError: unexpected EOF while parsing

如您所見,eval函數能夠識別字符串中的表達式並將其轉換為相應的類型。但是,當我們僅傳遞字符和字母時,它返回了一個錯誤。這應該清楚eval的實際作用。

這裡有更多的例子,其中我們不僅僅涉及類型轉換,實際上我們看到了eval函數評估字符串中的表達式。

我們還可以使用eval求解數學表達式:

<code> expr =「(2+(3 * 2))/ 2」 print(eval(expr))</ code>

我們甚至可以在字符串中使用變量名,Python還將對它們進行評估,如下所示
<code>num=10expr="(2+(3*2))/2 + num"print(eval(expr))</code>

我們還可以在字符串內部使用內置函數,如下所示:

<code>print(eval("sum([8, 16, 34])"))</code>

為了更好地了解eval函數,讓我們看看如果將表達式用兩個字符串括起來,它將如何響應,如下所示:

<code>#string in another stringexpr="'2+3'"print(eval(expr))print(eval(eval(expr)))</code>

因此,第一個eval函數只是返回字符串中的表達式,但是在另一個eval函數中使用eval時,我們得到了表達式的答案。

如何在python中使用eval ?

在上一節中,我們已經了解了如何使用eval函數,但是在這裡,我們將了解eval函數的其他參數如何影響其工作。因此,Python中的eval 還有兩個參數,即viz-globals和locals。

全局變量是當前全局範圍或命名空間中可用的對象。您可以從代碼中的任何位置訪問它們。

在執行時,傳遞給字典中全局變量的所有對象將對eval()可用。請查看以下示例,該示例顯示了如何使用自定義詞典為eval函數提供全局名稱空間:

<code>num1 = 100  print(eval("num1 + 100", {"num1": num1}))num2 = 200  print(eval("num1 + num2", {"num1": num1,"num2": num2}))print(eval("num1 + num2", {"num1": num1}))</code>

OUTPUT: 200                                                                                                                            300                                                                                                                            Traceback (most recent call last):                                                                                               File "main.py", line 5, in                                                                                               print(eval("num1 + num2", {"num1": num1}))                                                                                   File "", line 1, in                                                                                          NameError: name 'num2' is not defined

如您在上面的示例中看到的,首先eval只能訪問num1和num2,但是當我從globals字典中刪除num2時,它拋出了一個錯誤,因為它現在無法識別num2。

但是,為什麼在我甚至沒有將值傳遞給globals參數的上述示例中都沒有發生這種錯誤?

事實證明,當您在不提供globals參數的情況下調用eval函數時,該函數將使用globals()函數返回的字典作為其全局命名空間來評估表達式。

因此,在上面的示例中,我們可以自由訪問所有變量,因為它們是當前全局範圍中包含的全局變量。

現在,如果將空字典傳遞給全局變量會發生什麼,讓我們看看:

<code>a=2print(eval("sum([2, 2, 2])", {}))print(eval("sum([a, 2, 2])", {}))</code>

OUTPUT:6                                                                                                                              Traceback (most recent call last):                                                                                               File "main.py", line 3, in                                                                                               print(eval("sum([a, 2, 2])", {}))                                                                                            File "", line 1, in                                                                                          NameError: name 'a' is not defined

因此,eval函數可以成功識別函數和,但無法識別對象「 a」,因此返回錯誤。

當我們向全局變量提供自定義詞典時,它包含鍵「 __builtins__」的值,但如果不包含該值,則在解析表達式之前,將自動在「 __builtins__」下插入對內置字典的引用。這樣可以確保eval()函數在評估表達式時將完全訪問所有Python的內置名稱。這說明了在上面的示例中,如何通過eval識別函數和。

現在讓我們看看什麼是局部變量以及它們如何擴展eval函數的功能。與全局變量不同,局部對象在函數內部聲明,不能在函數外部訪問。

類似地,locals參數採用一個字典,在字典中我們添加了一些對象,而eval()函數將這些對象視為本地對象。請看下面的例子:

<code>print(eval("sum([a, 2, 2])",{}, {"a":2}))print(a)</code>

OUTPUT: 6                                                                                                                              Traceback (most recent call last):                                                                                               File "main.py", line 2, in                                                                                               print(a)                                                                                                                   NameError: name 'a' is not defined

請注意,要向本地人提供字典,您首先需要向全局人提供字典。不能將關鍵字參數與eval()一起使用

這似乎令人困惑,但是在下面的示例中,我同時使用了globals和locals參數,您將看到它們如何影響結果。

<code>print(eval("abs(-1)"))#By keeping __builtins__":None,eval will recognise no in-buiilt functionprint(eval('abs(-1)',{"__builtins__":None}))</code>

OUTPUT:1Traceback (most recent call last):                                                                                               File "main.py", line 1, in                                                                                               print(eval('abs(-1)',{"__builtins__":None}))                                                                                 File "", line 1, in                                                                                          TypeError: 'NoneType' object is not subscriptable

現在,我們希望該函數在eval函數中起作用,因此將其添加到本地字典中。現在,eval函數可以識別abs函數,而不能識別任何其他函數。

<code>print(eval('abs(-1)',{"__builtins__":None},{"abs":abs}))</code>

全局變量和局部變量之間的主要實際區別是,如果該密鑰尚不存在,Python會自動將「 __builtins__」鍵插入全局變量。無論是否為全局變量提供自定義詞典,都會發生這種情況。另一方面,如果向本地人提供自定義詞典,則在執行eval函數期間該詞典將保持不變。

評估的局限性

Python中的eval()很有用,但也有重要的安全隱患。eval函數被認為是不安全的,因為它允許您或其他用戶動態執行任意Python代碼。那對我們有什麼影響?

假設您正在伺服器上運行的應用程式中要求用戶輸入。現在,如果您在輸入上使用eval函數,則用戶可以訪問伺服器本身。用戶可以像這樣傳遞一些可疑的代碼:

<code> __ import __('subprocess')。getoutput('rm –rf *')</ code>

上面的代碼將刪除應用程式當前目錄中的所有文件,這肯定會影響我們。

因此,最好避免使用eval函數,但是如果仍然要使用eval函數,我們可以藉助globals和locals參數來限制其功能。正如我們在上一節中看到的那樣,我們限制eval函數,使其只能使用python的abs函數。

例如,假設我有一個應用程式,可以在給定數字或所有給定數字的總和中找到最小值。像這樣使用eval的最方便方法

<code> print(eval(input()))

但是,這是一種不好的編程方式。我們無法控制用戶的輸入內容,因此我們可以利用globals和locals參數,使得eval不能識別sum()和min()以外的函數。這肯定會和上面的代碼做同樣的事情,但是要安全得多。

<code> print(eval(input(),{「 __ builtins __」:None},{「 min」:min,「 sum」:sum}))</ code>


希望大家可以通過本文了解到Python中的 eval函數,如果您想了解更多有關python案例實操,建議下載閱讀「Python經典80案例實操

點個再看,證明你還愛我

相關焦點

  • [python]eval的「真香」定律
    和 「真相」 這兩方面以實例的形式介紹eval語法格式:eval(expression, globals=None,  locals=None)參數解析:expression:這個參數是一個字符串,python會使用globals字典和locals字典作為全局和局部的命名空間,將expression
  • 深度辨析 Python 的 eval() 與 exec()
    在《Python進階:如何將字符串常量轉為變量?》文中,我提到過 eval() 和 exec() ,但對它們並不太了解。為了彌補這方面知識,我就重新學習了下。這篇文章是一份超級詳細的學習記錄,系統、全面而深入地辨析了這兩大函數。
  • python eval()內置函數
    python有一個內置函數eval(),可以將字符串進行運行。
  • Python eval函數
    1、函數說明語法:eval(expression, globals=None, locals=None)參數說明:# expression=python字符串表達式(必選參數)# globals(字典類型)=在 globals字典中尋找參數expression當中定義的變量值 (可選參數)# locals (字典類型)=在locals字典中尋找參數expression當中定義的變量值 (可選參數)#當globals與locals 都被忽略的話在當前函數被調用環境中尋找參數expression當中定義的變量值
  • python的內置函數eval:字符串運算
    前言最先認識eval,是在javascript中,eval() 函數可計算某個字符串,並執行其中的的 JavaScript 代碼。在javascript中,該方法只接受原始字符串作為參數,如果 string 參數不是原始字符串,那麼該方法將不作任何改變地返回。因此請不要為 eval() 函數傳遞 String 對象來作為參數。
  • Python 的 eval() 與 exec() 安全用法最佳實踐
    然而,在實際使用過程中,存在很多微小的細節,此處就列出我所知道的幾點吧。 常見用途:將字符串轉成相應的對象,例如 string 轉成 list ,string 轉成 dict,string 轉 tuple 等等。
  • Python eval的用法及注意事項
    想像一下變量賦值時,將等號右邊的表達式寫成字符串的格式,將這個字符串作為eval的參數,eval的返回值就是這個表達式的結果。python中eval函數的用法十分的靈活,但也十分危險,安全性是其最大的缺點。本文從靈活性和危險性兩方面介紹eval。1、強大之處舉幾個例子感受一下,字符串與list、tuple、dict的轉化。
  • 乾貨 | 深度辨析 Python 的 eval() 與 exec()
    很多動態的程式語言中都會有 eval() 函數,作用大同小異,但是,無一例外,人們會告訴你說,避免使用它。為什麼要慎用 eval() 呢?主要出於安全考慮,對於不可信的數據源,eval 函數很可能會招來代碼注入的問題。
  • Python - 超級好用的函數eval
    前言eval是Python的一個內置函數,這個函數的作用是,返回傳入字符串的表達式的結果。即變量賦值時,等號右邊的表示是寫成字符串的格式,返回值就是這個表達式的結果。命名空間python是用命名空間來記錄變量的軌跡的,命名空間是一個dictionary,鍵是變量名,值是變量值。
  • 在JavaScript中為什麼不要使用eval
    為什麼不要使用evaleval函數會在當前作用域中執行一段 JavaScript 代碼字符串。但是 eval只在被直接調用並且調用函數就是eval本身時,才在當前作用域中執行。注意:上面的代碼等價於在全局作用域中調用eval,和下面兩種寫法效果一樣:在任何情況下我們都應該避免使用eval函數。99.9% 使用eval的場景都有不使用eval的解決方案。偽裝的eval定時函數 setTimeout和setInterval都可以接收字符串作為它們的第一個參數。
  • Python 中 eval 函數的神奇用法
    Python 中 Eval 函數的用法ambda的一般形式是關鍵字lambda後面跟一個或多個參數,緊跟一個冒號,以後是一個表達式
  • Python中的條件表達式,也稱之為三元運算符,使用方法和技巧
    Python中的條件表達式在其他程式語言中也稱之為三元運算符,在C#和JAVA中都有三元運算符,Python中的條件表達式是基於真(true)假(false)的條件進行判斷的,或者說三元運算符在操作的過程中使用了三個元素如:【條件為真的結果】
  • Python: eval函數的妙用和濫用
    (點擊上方快速關注並設置為星標,一起學Python)作者:The_Third_Wave     來源:https://blog.csdn.net/zhanh1218/article/details/37562167eval
  • Python 如何將字符串轉換成 json ?
    最近在工作中遇到了一個小問題,如果要將字符串型的數據轉換成dict類型,我第一時間就想到了使用json函數。
  • Python內置函數eval()用法及其安全問題
    >>>> a = 3>>> b = 5>>> eval('a+b')8這個函數在Python 3.x中使用較多,因為在Python 3.x中使用input()函數接收用戶輸入時一律返回字符串,經常需要進行類型轉換,這時候常使用eval()函數,例如:>>>
  • 自動執行文本中的 MATLAB 表達式——關於eval函數的使用技巧
    for i = 1:10    n = input(['n' num2str(i) '=']);   eval([ 'n',num2str(i),'=n'])endeval用於循環中是再好不過了,特別是有些變量的名字中含有有規律的數字,比如我們現在要依次把data1,data2,data3寫入excel,並命名為data1.
  • python基礎-input函數和eval函數
    1、input()函數的使用方法下面舉個例子來說明:比如我們要做一個計算體脂率的小程序,需要用戶輸入身高和體重,可以這樣來做height=input()#輸入身高信息,用逗號隔開,輸入完成後敲回車weight=input()#輸入體重信息,用逗號隔開,輸入完成後敲回車注意程序讀到input這一行的時候,會自動暫停等待,等用戶輸入完信息,才會運行下一行代碼
  • 代碼詳解:如何用Python運行高性能的數學範式?
    全文共1140字,預計學習時長3分鐘比較python中不同運行範式的表現情況那麼,在開發和學習中有哪些技巧呢?首先需要明確的是:編寫python代碼和編寫pythonic代碼之間存在很大差異。這篇文章圍繞一些最常用的數據科學操作編寫了最佳(也存在爭議的)實踐。
  • python中的這些坑,早看早避免.
    說一說python中遇到的坑,躲坑看這一篇就夠了傳遞參數時候不要使用列表 def foo(num,age=[]):    age.append(num)    print("num",num)    return ageprint(foo(1))print(foo(2))print(foo(3))
  • Python json中一直搞不清的load、loads、dump、dumps、eval
    做接口測試的時候,有時候需要對字符串、json串進行一些轉換,可是總是得花費一些時間,本質來說還是有可能是這幾個方法的使用沒有弄清楚。