您好,登錄后才能下訂單哦!
如何在python3項(xiàng)目中中eval函數(shù)?很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
python中eval函數(shù)的用法十分的靈活,這里主要介紹一下它的原理和一些使用的場(chǎng)合。
下面是從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.
下面我做一下簡(jiǎn)單的翻譯,有可能有一些翻譯不好的地方,見諒。
函數(shù)原型:
eval(expression, globals=None, locals=None)
參數(shù):
expression:這個(gè)參數(shù)是一個(gè)字符串,python會(huì)使用globals字典和locals字典作為全局和局部的命名空間,將expression當(dāng)做一個(gè)python表達(dá)式(從技術(shù)上講,是一個(gè)條件列表)進(jìn)行解析和計(jì)算。
globals:這個(gè)參數(shù)管控的是一個(gè)全局的命名空間,也就是我們?cè)谟?jì)算表達(dá)式的時(shí)候可以使用全局的命名空間中的函數(shù),如果這個(gè)參數(shù)被提供了,并且沒有提供自定義的__builtins__,那么會(huì)將當(dāng)前環(huán)境中的__builtins__拷貝到自己提供的globals里,然后才會(huì)進(jìn)行計(jì)算。關(guān)于__builtins__,它是python的內(nèi)建模塊,也就是python自帶的模塊,不需要我們import就可以使用的,例如我們平時(shí)使用的int、str、abs等都在這個(gè)模塊中。如果globals沒有被提供,則使用python的全局命名空間。
locals:這個(gè)參數(shù)管控的是一個(gè)局部的命名空間,和globals類似,不過當(dāng)它和globals中有重復(fù)的部分時(shí),locals里的定義會(huì)覆蓋掉globals中的,也就是當(dāng)globals和locals中有沖突的部分時(shí),locals說了算,它有決定權(quán),以它的為準(zhǔn)。如果locals沒有被 提供的話,則默認(rèn)為globals。
eval函數(shù)也可以被用來執(zhí)行任意的代碼對(duì)象(如那些由compile()創(chuàng)建的對(duì)象)。在這種情況下,expression參數(shù)是一個(gè)代碼對(duì)象而不是一個(gè)字符串。如果代碼對(duì)象已經(jīng)被‘exec‘編譯為模式參數(shù),eavl()的返回值是None。
下面舉一些例子進(jìn)行講解:
三個(gè)參數(shù)的使用:
1、在前兩個(gè)參數(shù)省略的情況下,eval在當(dāng)前的作用域執(zhí)行:
a=10; print(eval("a+1"))
執(zhí)行結(jié)果為:11
在這種情況下,后兩個(gè)參數(shù)省略了,所以eval中的a是前面的10。對(duì)于eval,它會(huì)將第一個(gè)expression字符串參數(shù)的引號(hào)去掉,然后對(duì)引號(hào)中的式子進(jìn)行解析和計(jì)算。
2、在globals指定的情況下:
a=10; g={'a':4} print(eval("a+1",g))
執(zhí)行結(jié)果為:5
這里面可能有點(diǎn)繞啊,初學(xué)者得理理清楚。在這次的代碼中,我們?cè)?eval中提供了globals參數(shù),這時(shí)候eval的作用域就是g指定的這個(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í)行的結(jié)果為:116
這里面就更有點(diǎn)繞人了,此次執(zhí)行的結(jié)果中,a是6,b是100,c是10。我們首先來看一下,對(duì)于a為6我們是沒有疑問的,因?yàn)樵谏蟼€(gè)例子中已經(jīng)說了,g會(huì)屏蔽程序中的全局變量的,而這里最主要的是為什么b是100呢?還記得我們?cè)趨?shù)介紹的時(shí)候說過,當(dāng)locals和globals起沖突時(shí),locals是起決定作用的,這在很多編程語言里都是一樣的,是作用域的覆蓋問題,當(dāng)前指定的小的作用域會(huì)覆蓋以前大的作用域,這可以理解為一張小的紙蓋在了一張大的紙上,紙是透明的,上面寫的東西是不透明的,而它們重合的地方就可以理解成兩個(gè)作用域沖突的地方,自然是小的顯現(xiàn)出來了。
使用的場(chǎng)合
對(duì)于eval的使用,我們一定要確保第一個(gè)參數(shù)expression滿足表達(dá)式的要求,它是可以被解析然后計(jì)算的。
s="abck" print(eval(s))
執(zhí)行的結(jié)果為:NameError: name 'abck' is not defined
對(duì)于當(dāng)面的代碼,我們可以看到,字符串s并不滿足表達(dá)式的要求。當(dāng)eval剝?nèi)チ?quot;abck"的外面的引號(hào)的時(shí)候,它會(huì)對(duì)它進(jìn)行解析,然后滿足要求后進(jìn)行計(jì)算,然后它解析到的是abcd,請(qǐng)注意,程序報(bào)出的錯(cuò)誤是NameError,也就是說,當(dāng)它解析到這個(gè)表達(dá)式是不可以計(jì)算后,它就會(huì)查找它是不是一個(gè)變量的名字,如果是一個(gè)變量的名字,那么它會(huì)輸出這個(gè)變量的內(nèi)容,否則就會(huì)產(chǎn)生這種報(bào)錯(cuò)。
s="abck" print(eval('s'))
執(zhí)行的結(jié)果為:abck
對(duì)于這個(gè)代碼,我們就可以看出來了,eval首先將‘s'的引號(hào)剝?nèi)?,然后得到的是s,顯然這個(gè)是不可以進(jìn)行計(jì)算的,那么它就開始查找s是否是一個(gè)變量的名字,然后它一查找,果然s是一個(gè)字符串,所以程序輸出了s中的內(nèi)容。
在上面一直說到expression的要求,那么它到底是什么具體要求呢?下面仍然通過例子進(jìn)行說明。
s='"sas"' print(eval(s))
執(zhí)行的結(jié)果為:sas
對(duì)于這個(gè)代碼,我們繼續(xù)分析,eval首先去除單引號(hào),eval在執(zhí)行的時(shí)候是只會(huì)去除同種類型的引號(hào)的,對(duì)于單引號(hào)和雙引號(hào)它是加以區(qū)分的。eval去除單引號(hào)后得到了“sas”,這個(gè)時(shí)候程序解析到它是一個(gè)字符串,不可以計(jì)算,就輸出了它。那么不禁想問,為什么上個(gè)例子中s="abck"會(huì)不行呢,這里面我們就可以看出區(qū)別了,一個(gè)是有引號(hào)括起來的,一個(gè)是沒有的,引號(hào)括起來代表字符串,雖然不可以求值,但是是有意義的,可以進(jìn)行輸出,而沒引號(hào)的便無法判斷“身份”了,只能當(dāng)做變量名進(jìn)行解析,而abck并不是一個(gè)變量名,所以就報(bào)錯(cuò)了。
s='["a","b","c"]' print(eval(s))
執(zhí)行的結(jié)果為:['a', 'b', 'c']
對(duì)于這個(gè)程序就不多做解釋了,eval去除引號(hào)后會(huì)檢查到它是不可計(jì)算的,但它是一個(gè)列表,便輸出了里面的內(nèi)容。
a=10 b=20 c=30 s='[a,b,c]' print(eval(s))
執(zhí)行的結(jié)果為:[10, 20, 30]
對(duì)于這個(gè)程序的結(jié)果,是不是有點(diǎn)意外,這里需要說明的是,eval檢查到列表的‘['‘]'符號(hào)時(shí),是會(huì)對(duì)里面的元素進(jìn)行解析的,這里a、b、c顯然不是具體的數(shù)據(jù),便去查找它們是否是變量名,然后確認(rèn)是變量名后,用它們的內(nèi)容替換掉它。
s='abs(10)' print(eval(s))
執(zhí)行的結(jié)果為:10
對(duì)于這個(gè)程序,我們舉的是一個(gè)滿足計(jì)算的一個(gè)表達(dá)式,當(dāng)eval剝?nèi)的引號(hào)后,得到abs(10),然后它會(huì)對(duì)進(jìn)行解析,這個(gè)解析我們前面介紹eval的時(shí)候說過,它會(huì)使用globals的內(nèi)建模塊__builtins__進(jìn)行解析的,在這個(gè)內(nèi)建模塊中是有abs這個(gè)函數(shù)的,所以對(duì)abs(10)進(jìn)行了計(jì)算。
關(guān)于__builtins__模塊中有哪些東西 ,我們可以這樣查看:
print(dir(__builtins__))
執(zhí)行結(jié)果為:
['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']
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。