python3中eval函數用法使用簡介
python中eval函數的用法十分的靈活,這里主要介紹一下它的原理和一些使用的場合。
下面是從python的官方文檔中的解釋:
The arguments are a string and optional globals and locals. If provided, globals must be a dictionary. If provided, locals can be any mapping object.
The expression argument is parsed and evaluated as a Python expression (technically speaking, a condition list) using the globals and locals dictionaries as global and local namespace. If the globals dictionary is present and lacks ‘__builtins__', the current globals are copied into globals before expression is parsed. This means that expression normally has full access to the standard builtins module and restricted environments are propagated. If the locals dictionary is omitted it defaults to the globals dictionary. If both dictionaries are omitted, the expression is executed in the environment where eval() is called. The return value is the result of the evaluated expression. Syntax errors are reported as exceptions. Example:
>>> x = 1
>>> eval('x+1')
This function can also be used to execute arbitrary code objects (such as those created by compile()). In this case pass a code object instead of a string. If the code object has been compiled with 'exec' as the mode argument, eval()‘s return value will be None.
Hints: dynamic execution of statements is supported by the exec() function. The globals() and locals() functions returns the current global and local dictionary, respectively, which may be useful to pass around for use by eval() or exec().
See ast.literal_eval() for a function that can safely evaluate strings with expressions containing only literals.
下面我做一下簡單的翻譯,有可能有一些翻譯不好的地方,見諒。
函數原型:
eval(expression, globals=None, locals=None)
參數:
expression:這個參數是一個字符串,python會使用globals字典和locals字典作為全局和局部的命名空間,將expression當做一個python表達式(從技術上講,是一個條件列表)進行解析和計算。
globals:這個參數管控的是一個全局的命名空間,也就是我們在計算表達式的時候可以使用全局的命名空間中的函數,如果這個參數被提供了,并且沒有提供自定義的__builtins__,那么會將當前環(huán)境中的__builtins__拷貝到自己提供的globals里,然后才會進行計算。關于__builtins__,它是python的內建模塊,也就是python自帶的模塊,不需要我們import就可以使用的,例如我們平時使用的int、str、abs等都在這個模塊中。如果globals沒有被提供,則使用python的全局命名空間。
locals:這個參數管控的是一個局部的命名空間,和globals類似,不過當它和globals中有重復的部分時,locals里的定義會覆蓋掉globals中的,也就是當globals和locals中有沖突的部分時,locals說了算,它有決定權,以它的為準。如果locals沒有被 提供的話,則默認為globals。
eval函數也可以被用來執(zhí)行任意的代碼對象(如那些由compile()創(chuàng)建的對象)。在這種情況下,expression參數是一個代碼對象而不是一個字符串。如果代碼對象已經被‘exec‘編譯為模式參數,eavl()的返回值是None。
下面舉一些例子進行講解:
三個參數的使用:
1、在前兩個參數省略的情況下,eval在當前的作用域執(zhí)行:
a=10;
print(eval("a+1"))
執(zhí)行結果為:11
在這種情況下,后兩個參數省略了,所以eval中的a是前面的10。對于eval,它會將第一個expression字符串參數的引號去掉,然后對引號中的式子進行解析和計算。
2、在globals指定的情況下:
a=10;
g={'a':4}
print(eval("a+1",g))
執(zhí)行結果為:5
這里面可能有點繞啊,初學者得理理清楚。在這次的代碼中,我們在 eval中提供了globals參數,這時候eval的作用域就是g指定的這個字典了,也就是外面的a=10被屏蔽掉了,eval是看不見的,所以使用了a為4的值。
3、在 locals指定的情況下 :
a=10
b=20
c=30
g={'a':6,'b':8}
t={'b':100,'c':10}
print(eval('a+b+c',g,t))
執(zhí)行的結果為:116
這里面就更有點繞人了,此次執(zhí)行的結果中,a是6,b是100,c是10。我們首先來看一下,對于a為6我們是沒有疑問的,因為在上個例子中已經說了,g會屏蔽程序中的全局變量的,而這里最主要的是為什么b是100呢?還記得我們在參數介紹的時候說過,當locals和globals起沖突時,locals是起決定作用的,這在很多編程語言里都是一樣的,是作用域的覆蓋問題,當前指定的小的作用域會覆蓋以前大的作用域,這可以理解為一張小的紙蓋在了一張大的紙上,紙是透明的,上面寫的東西是不透明的,而它們重合的地方就可以理解成兩個作用域沖突的地方,自然是小的顯現出來了。
使用的場合
對于eval的使用,我們一定要確保第一個參數expression滿足表達式的要求,它是可以被解析然后計算的。
s="abck" print(eval(s))
執(zhí)行的結果為:NameError: name 'abck' is not defined
對于當面的代碼,我們可以看到,字符串s并不滿足表達式的要求。當eval剝去了"abck"的外面的引號的時候,它會對它進行解析,然后滿足要求后進行計算,然后它解析到的是abcd,請注意,程序報出的錯誤是NameError,也就是說,當它解析到這個表達式是不可以計算后,它就會查找它是不是一個變量的名字,如果是一個變量的名字,那么它會輸出這個變量的內容,否則就會產生這種報錯。
s="abck"
print(eval('s'))
執(zhí)行的結果為:abck
對于這個代碼,我們就可以看出來了,eval首先將‘s'的引號剝去,然后得到的是s,顯然這個是不可以進行計算的,那么它就開始查找s是否是一個變量的名字,然后它一查找,果然s是一個字符串,所以程序輸出了s中的內容。
在上面一直說到expression的要求,那么它到底是什么具體要求呢?下面仍然通過例子進行說明。
s='"sas"' print(eval(s))
執(zhí)行的結果為:sas
對于這個代碼,我們繼續(xù)分析,eval首先去除單引號,eval在執(zhí)行的時候是只會去除同種類型的引號的,對于單引號和雙引號它是加以區(qū)分的。eval去除單引號后得到了“sas”,這個時候程序解析到它是一個字符串,不可以計算,就輸出了它。那么不禁想問,為什么上個例子中s="abck"會不行呢,這里面我們就可以看出區(qū)別了,一個是有引號括起來的,一個是沒有的,引號括起來代表字符串,雖然不可以求值,但是是有意義的,可以進行輸出,而沒引號的便無法判斷“身份”了,只能當做變量名進行解析,而abck并不是一個變量名,所以就報錯了。
s='["a","b","c"]' print(eval(s))
執(zhí)行的結果為:['a', 'b', 'c']
對于這個程序就不多做解釋了,eval去除引號后會檢查到它是不可計算的,但它是一個列表,便輸出了里面的內容。
a=10 b=20 c=30 s='[a,b,c]' print(eval(s))
執(zhí)行的結果為:[10, 20, 30]
對于這個程序的結果,是不是有點意外,這里需要說明的是,eval檢查到列表的‘['‘]'符號時,是會對里面的元素進行解析的,這里a、b、c顯然不是具體的數據,便去查找它們是否是變量名,然后確認是變量名后,用它們的內容替換掉它。
s='abs(10)' print(eval(s))
執(zhí)行的結果為:10
對于這個程序,我們舉的是一個滿足計算的一個表達式,當eval剝去s的引號后,得到abs(10),然后它會對進行解析,這個解析我們前面介紹eval的時候說過,它會使用globals的內建模塊__builtins__進行解析的,在這個內建模塊中是有abs這個函數的,所以對abs(10)進行了計算。
關于__builtins__模塊中有哪些東西 ,我們可以這樣查看:
print(dir(__builtins__))
執(zhí)行結果為:
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
在這里我們可以看見這個模塊中所有的東西,eval在進行計算的時候也是在這里進行查找的
到這里,eval的解釋說明就結束了。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
numpy矩陣乘法中的multiply,matmul和dot的使用
本文主要介紹了numpy矩陣乘法中的multiply,matmul和dot的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-02-02
python?flask項目打包成docker鏡像發(fā)布的過程
這篇文章主要介紹了python?flask項目打包成docker鏡像發(fā)布,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03
解決pycharm安裝scrapy DLL load failed:找不到指定的程序的問題
很多朋友向小編求助pycharm安裝scrapy DLL load failed:找不到指定的程序的問題,就這一問題小編在window10 + anaconda3 +pycharm2020.1.1 + scrapy安裝親測可用,下面把我的處理過程分享到腳本之家平臺,供大家參考2021-06-06
python的tkinter、socket庫開發(fā)tcp的客戶端和服務端詳解
本文介紹了TCP通訊流程和開發(fā)步驟,包括客戶端和服務端的實現,客戶端使用Python的tkinter庫實現圖形化界面,服務端使用socket庫監(jiān)聽連接并處理消息,文章還提供了客戶端和服務端的代碼示例2025-01-01

