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')
2

   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__,那麼會將當前環境中的__builtins__拷貝到自己提供的globals裏,然後纔會進行計算。關於__builtins__,它是python的內建模塊,也就是python自帶的模塊,不需要我們import就可以使用的,例如我們平時使用的int、str、abs等都在這個模塊中。關於它的說明可以參照這篇文章:點擊打開鏈接。如果globals沒有被提供,則使用python的全局命名空間。

locals:這個參數管控的是一個局部的命名空間,和globals類似,不過當它和globals中有重複的部分時,locals裏的定義會覆蓋掉globals中的,也就是當globals和locals中有衝突的部分時,locals說了算,它有決定權,以它的爲準。如果locals沒有被 提供的話,則默認爲globals。

        eval函數也可以被用來執行任意的代碼對象(如那些由compile()創建的對象)。在這種情況下,expression參數是一個代碼對象而不是一個字符串。如果代碼對象已經被‘exec‘編譯爲模式參數,eavl()的返回值是None。

下面舉一些例子進行講解:

三個參數的使用:

1、在前兩個參數省略的情況下,eval在當前的作用域執行:

a=10;
print(eval("a+1"))
執行結果爲:11

        在這種情況下,後兩個參數省略了,所以eval中的a是前面的10。對於eval,它會將第一個expression字符串參數的引號去掉,然後對引號中的式子進行解析和計算。

2、在globals指定的情況下:

a=10;
g={'a':4}
print(eval("a+1",g))
執行結果爲: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))
執行的結果爲:116

       這裏面就更有點繞人了,此次執行的結果中,a是6,b是100,c是10。我們首先來看一下,對於a爲6我們是沒有疑問的,因爲在上個例子中已經說了,g會屏蔽程序中的全局變量的,而這裏最主要的是爲什麼b是100呢?還記得我們在參數介紹的時候說過,當locals和globals起衝突時,locals是起決定作用的,這在很多編程語言裏都是一樣的,是作用域的覆蓋問題,當前指定的小的作用域會覆蓋以前大的作用域,這可以理解爲一張小的紙蓋在了一張大的紙上,紙是透明的,上面寫的東西是不透明的,而它們重合的地方就可以理解成兩個作用域衝突的地方,自然是小的顯現出來了。

使用的場合

          對於eval的使用,我們一定要確保第一個參數expression滿足表達式的要求,它是可以被解析然後計算的。

s="abck"
print(eval(s))
執行的結果爲:NameError: name 'abck' is not defined

        對於當面的代碼,我們可以看到,字符串s並不滿足表達式的要求。當eval剝去了"abck"的外面的引號的時候,它會對它進行解析,然後滿足要求後進行計算,然後它解析到的是abcd,請注意,程序報出的錯誤是NameError,也就是說,當它解析到這個表達式是不可以計算後,它就會查找它是不是一個變量的名字,如果是一個變量的名字,那麼它會輸出這個變量的內容,否則就會產生這種報錯。

s="abck"
print(eval('s')) 
執行的結果爲:abck

        對於這個代碼,我們就可以看出來了,eval首先將‘s’的引號剝去,然後得到的是s,顯然這個是不可以進行計算的,那麼它就開始查找s是否是一個變量的名字,然後它一查找,果然s是一個字符串,所以程序輸出了s中的內容。

       在上面一直說到expression的要求,那麼它到底是什麼具體要求呢?下面仍然通過例子進行說明。

s='"sas"'
print(eval(s))
執行的結果爲:sas

       對於這個代碼,我們繼續分析,eval首先去除單引號,eval在執行的時候是隻會去除同種類型的引號的,對於單引號和雙引號它是加以區分的。eval去除單引號後得到了“sas”,這個時候程序解析到它是一個字符串,不可以計算,就輸出了它。那麼不禁想問,爲什麼上個例子中s="abck"會不行呢,這裏面我們就可以看出區別了,一個是有引號括起來的,一個是沒有的,引號括起來代表字符串,雖然不可以求值,但是是有意義的,可以進行輸出,而沒引號的便無法判斷“身份”了,只能當做變量名進行解析,而abck並不是一個變量名,所以就報錯了。

s='["a","b","c"]'
print(eval(s))
執行的結果爲:['a', 'b', 'c']

       對於這個程序就不多做解釋了,eval去除引號後會檢查到它是不可計算的,但它是一個列表,便輸出了裏面的內容。

a=10
b=20
c=30
s='[a,b,c]'
print(eval(s))
執行的結果爲:[10, 20, 30]

       對於這個程序的結果,是不是有點意外,這裏需要說明的是,eval檢查到列表的‘[’‘]’符號時,是會對裏面的元素進行解析的,這裏a、b、c顯然不是具體的數據,便去查找它們是否是變量名,然後確認是變量名後,用它們的內容替換掉它。

s='abs(10)'
print(eval(s))
執行的結果爲:10

       對於這個程序,我們舉的是一個滿足計算的一個表達式,當eval剝去s的引號後,得到abs(10),然後它會對進行解析,這個解析我們前面介紹eval的時候說過,它會使用globals的內建模塊__builtins__進行解析的,在這個內建模塊中是有abs這個函數的,所以對abs(10)進行了計算。

      關於__builtins__模塊中有哪些東西 ,我們可以這樣查看:

print(dir(__builtins__))
執行結果爲:

['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的解釋說明就結束了。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章