Python基礎_eval(),exec(),globals(),locals(),compile()

轉發:http://www.cnblogs.com/yyds/p/6276746.htmlhtml

1. eval函數


函數的做用:

計算指定表達式的值。也就是說它要執行的Python代碼只能是單個運算表達式(注意eval不支持任意形式的賦值操做),而不能是複雜的代碼邏輯,這一點和lambda表達式比較類似。python

函數定義:

eval(expression, globals=None, locals=None)

參數說明:

  • expression:必選參數,能夠是字符串,也能夠是一個任意的code對象實例(能夠經過compile函數建立)。若是它是一個字符串,它會被看成一個(使用globals和locals參數做爲全局和本地命名空間的)Python表達式進行分析和解釋。
  • globals:可選參數,表示全局命名空間(存放全局變量),若是被提供,則必須是一個字典對象。
  • locals:可選參數,表示當前局部命名空間(存放局部變量),若是被提供,能夠是任何映射對象。若是該參數被忽略,那麼它將會取與globals相同的值。
  • 若是globals與locals都被忽略,那麼它們將取eval()函數被調用環境下的全局命名空間和局部命名空間。

返回值:

  • 若是expression是一個code對象,且建立該code對象時,compile函數的mode參數是'exec',那麼eval()函數的返回值是None;
  • 不然,若是expression是一個輸出語句,如print(),則eval()返回結果爲None;
  • 不然,expression表達式的結果就是eval()函數的返回值;

實例:

x = 10 def func(): y = 20 a = eval('x + y') print('a: ', a) b = eval('x + y', {'x': 1, 'y': 2}) print('b: ', b) c = eval('x + y', {'x': 1, 'y': 2}, {'y': 3, 'z': 4}) print('c: ', c) d = eval('print(x, y)') print('d: ', d) func()

輸出結果:express

a: 30 b: 3 c: 4 10 20 d: None

對輸出結果的解釋:ide

  • 對於變量a,eval函數的globals和locals參數都被忽略了,所以變量x和變量y都取得的是eval函數被調用環境下的做用域中的變量值,即:x = 10, y = 20,a = x + y = 30
  • 對於變量b,eval函數只提供了globals參數而忽略了locals參數,所以locals會取globals參數的值,即:x = 1, y = 2,b = x + y = 3
  • 對於變量c,eval函數的globals參數和locals都被提供了,那麼eval函數會先從所有做用域globals中找到變量x, 從局部做用域locals中找到變量y,即:x = 1, y = 3, c = x + y = 4
  • 對於變量d,由於print()函數不是一個計算表達式,沒有計算結果,所以返回值爲None

2. exec函數


函數的做用:

動態執行Python代碼。也就是說exec能夠執行復雜的Python代碼,而不像eval函數那麼樣只能計算一個表達式的值。函數

函數定義:

exec(object[, globals[, locals]])

參數說明:

  • object:必選參數,表示須要被指定的Python代碼。它必須是字符串或code對象。若是object是一個字符串,該字符串會先被解析爲一組Python語句,而後在執行(除非發生語法錯誤)。若是object是一個code對象,那麼它只是被簡單的執行。
  • globals:可選參數,同eval函數
  • locals:可選參數,同eval函數

返回值:

exec函數的返回值永遠爲None.ui

須要說明的是在Python 2中exec不是函數,而是一個內置語句(statement),可是Python 2中有一個execfile()函數。能夠理解爲Python 3把exec這個statement和execfile()函數的功可以整合到一個新的exec()函數中去了:this

eval()函數與exec()函數的區別:

  • eval()函數只能計算單個表達式的值,而exec()函數能夠動態運行代碼段。
  • eval()函數能夠有返回值,而exec()函數返回值永遠爲None。
# !usr/bin/env python

# coding:utf-8


_globals = {'name': 'tom', 'data': [18, 73, 84]}
_locals = {'a': 1, 'b': 2}

code = '''
def hellocute():
    return  "name %s ,age %d" %(name,data[0],)
'''

func = compile(code, '<string>', "exec")

"""
一、func裏輸入的變量(上面的name和data),先從_globals傳入,若是_globals=None,則從globals()傳入
二、func輸出的函數,先輸出到_locals,若是_locals=None,則輸出到_globals,若是_globals=None,則輸出到globals()


狀況1
exec(func)  # 默認參數均爲None
name = "tom"  # 因爲上面傳入None,因此須要在全局定義
data = [1,2,3,4]
print(hellocute())  # name tom ,age 1
func從全局即globals傳入參數,同時新建立的變量如func也輸出到globals裏

狀況2
exec(func,_globals,None)
print(_globals["hellocute"]())  # name tom ,age 18
print(_globals.keys())  # dict_keys(['name', 'data', '__builtins__', 'hellocute'])
若是存在字典參數_globals,而_locals爲None,則輸入輸出都到_globals裏,同時,_globals會也會被傳入一個k是__builtins__,v是globals()+python自帶函數等

狀況3
exec(func,None,_locals)
# print(_locals["hellocute"]())  # 報錯
print(_locals.keys())  # dict_keys(['a', 'b', 'hellocute'])
# name/data從globals(),因爲未定義,因此若是func執行的話會報錯
# func名傳入_locals

狀況4
exec(func,_globals,_locals)
print(_globals.keys())  # dict_keys(['name', 'data', '__builtins__'])
print(_locals.keys())  # dict_keys(['a', 'b', 'hellocute'])
print(_locals["hellocute"]())  # name tom ,age 18
從_globals傳入name/data,"hellocute"輸出到_locals

"""
補充:例子 對參數globals和locals的實驗

 

實例1:

咱們把實例1中的eval函數換成exec函數試試:spa

x = 10 def func(): y = 20 a = exec('x + y') print('a: ', a) b = exec('x + y', {'x': 1, 'y': 2}) print('b: ', b) c = exec('x + y', {'x': 1, 'y': 2}, {'y': 3, 'z': 4}) print('c: ', c) d = exec('print(x, y)') print('d: ', d) func()

輸出結果:翻譯

a:  None b: None c: None 10 20 d: None

由於咱們說過了,exec函數的返回值永遠爲None。code

實例2:

x = 10 expr = """ z = 30 sum = x + y + z print(sum) """ def func(): y = 20 exec(expr) exec(expr, {'x': 1, 'y': 2}) exec(expr, {'x': 1, 'y': 2}, {'y': 3, 'z': 4}) func()

輸出結果:

60
33
34

對輸出結果的解釋:

前兩個輸出跟上面解釋的eval函數執行過程同樣,不作過多解釋。關於最後一個數字34,咱們能夠看出是:x = 1, y = 3是沒有疑問的。關於z爲何仍是30而不是4,這其實也很簡單,咱們只須要在理一下代碼執行過程就能夠了,其執行過程至關於:

x = 1 y = 2 def func(): y = 3 z = 4 z = 30 sum = x + y + z print(sum) func()

3. globals()與locals()函數


函數定義及功能說明:

先來看下這兩個函數的定義和文檔描述

globals()

描述: Return a dictionary representing the current global symbol table. This is always the dictionary of the current module (inside a function or method, this is the module where it is defined, not the module from which it is called).

翻譯: 返回一個表示當前全局標識符表的字典。這永遠是當前模塊的字典(在一個函數或方法內部,這是指定義該函數或方法的模塊,而不是調用該函數或方法的模塊)

locals()

描述: Update and return a dictionary representing the current local symbol table. Free variables are returned by locals() when it is called in function blocks, but not in class blocks.

Note The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.

翻譯: 更新並返回一個表示當前局部標識符表的字典。自由變量在函數內部被調用時,會被locals()函數返回;自由變量在類累不被調用時,不會被locals()函數返回。

注意: locals()返回的字典的內容不該該被改變;若是必定要改變,不該該影響被解釋器使用的局部變量和自由變量。

總結:

  • globals()函數以字典的形式返回的定義該函數的模塊內的全局做用域下的全部標識符(變量、常量等)
  • locals()函數以字典的形式返回當前函數內的局域做用域下的全部標識符
  • 若是直接在模塊中調用globals()和locals()函數,它們的返回值是相同的

實例1:

name = 'Tom' age = 18 def func(x, y): sum = x + y _G = globals() _L = locals() print(id(_G), type(_G), _G) print(id(_L), type(_L), _L) func(10, 20)

輸出結果:

2131520814344 <class 'dict'> {'__builtins__': <module 'builtins' (built-in)>, 'func': <function func at 0x000001F048C5E048>, '__doc__': None, '__file__': 'C:/Users/wader/PycharmProjects/LearnPython/day04/func5.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F048BF4C50>, '__spec__': None, 'age': 18, '__name__': '__main__', 'name': 'Tom', '__package__': None, '__cached__': None} 2131524302408 <class 'dict'> {'y': 20, 'x': 10, '_G': {'__builtins__': <module 'builtins' (built-in)>, 'func': <function func at 0x000001F048C5E048>, '__doc__': None, '__file__': 'C:/Users/wader/PycharmProjects/LearnPython/day04/func5.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F048BF4C50>, '__spec__': None, 'age': 18, '__name__': '__main__', 'name': 'Tom', '__package__': None, '__cached__': None}, 'sum': 30}

實例2:

name = 'Tom' age = 18 G = globals() L = locals() print(id(G), type(G), G) print(id(L), type(L), L)

輸出結果:

2494347312392 <class 'dict'> {'__file__': 'C:/Users/wader/PycharmProjects/LearnPython/day04/func5.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000244C2E44C50>, 'name': 'Tom', '__spec__': None, '__builtins__': <module 'builtins' (built-in)>, '__cached__': None, 'L': {...}, '__package__': None, '__name__': '__main__', 'G': {...}, '__doc__': None, 'age': 18} 2494347312392 <class 'dict'> {'__file__': 'C:/Users/wader/PycharmProjects/LearnPython/day04/func5.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000244C2E44C50>, 'name': 'Tom', '__spec__': None, '__builtins__': <module 'builtins' (built-in)>, '__cached__': None, 'L': {...}, '__package__': None, '__name__': '__main__', 'G': {...}, '__doc__': None, 'age': 18}

上面打印出的G和L的內存地址是同樣的,說明在模塊級別locals()的返回值和globals()的返回值是相同的。

4. compile函數


函數的做用:

將source編譯爲code對象或AST對象。code對象可以經過exec()函數來執行或者經過eval()函數進行計算求值。

函數定義:

compile(source, filename, mode[, flags[, dont_inherit]])

參數說明:

  • source:字符串或AST(Abstract Syntax Trees)對象,表示須要進行編譯的Python代碼
  • filename:指定須要編譯的代碼文件名稱,若是不是從文件讀取代碼則傳遞一些可辨認的值(一般是用'<string>')
  • mode:用於標識必須當作那類代碼來編譯;若是source是由一個代碼語句序列組成,則指定mode='exec';若是source是由單個表達式組成,則指定mode='eval';若是source是由一個單獨的交互式語句組成,則指定mode='single'。
  • 另外兩個可選參數暫不作介紹

實例:

s = """ for x in range(10): print(x, end='') print() """ code_exec = compile(s, '<string>', 'exec') code_eval = compile('10 + 20', '<string>', 'eval') code_single = compile('name = input("Input Your Name: ")', '<string>', 'single') a = exec(code_exec) b = eval(code_eval) c = exec(code_single) d = eval(code_single) print('a: ', a) print('b: ', b) print('c: ', c) print('name: ', name) print('d: ', d) print('name; ', name)

輸出結果:

0123456789 Input Your Name: Tom Input Your Name: Jerry a: None b: 30 c: None name: Jerry d: None name; Jerry

5. 這幾個函數的關係


comiple()函數、globals()函數、locals()函數的返回結果能夠看成eval()函數與exec()函數的參數使用。

另外,咱們能夠經過判斷globals()函數的返回值中是否包含某個key來判斷,某個全局變量是否已經存在(被定義)。

相關文章
相關標籤/搜索