Python中兩大神器&exec() &eval()


一、神器1 —— 內置函數eval

eval是python中的內置函數,它的作用是將字符串變為所對應的表達式,也相當於一個功能代碼加雙引號變為字符串,而eval又將字符串轉為相應的功能,它在使用過程中有絕對的優勢,但是也存在使用風險,所以要在程序中正確使用,本人建議不要使用

eval的語法格式如下:

eval(expression[, globals[, locals]])
expression : 字符串
globals : 變量作用域,全局命名空間,如果被提供,則必須是一個字典對象。
locals : 變量作用域,局部命名空間,如果被提供,可以是任何映射對象。

結合globals和locals看看幾個例子

傳遞globals參數值為{“age”:1822},
b = eval("{'name':'linux','age':age}",{"age":1822})
print(b)

結果:{‘name’: ‘linux’, ‘age’: 1822}
再加上locals變量
age=18
b = eval("{'name':'linux','age':age}",{"age":1822},locals())
print(b)

結果:{'name': 'linux', 'age': 18}

通過上述示例可以看出:

當只使用全局變量globals,不使用局部變量locals時,查找全局是否存在變量,如果存在則用全局的變量
如果同時使用全局和局部,優先查找局部locals中的變量,其次在找全局globals中的變量,局部參數中同名變量會覆蓋全局中的變量的值,遵循取值順序(局部—>全局—>內置)

1.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)


func()

結果:a 30
     b 3
     c 4

eval函數實現list、dict、tuple與str之間的轉化

字符串轉換成列表b = eval("[[1,2], [3,4], [5,6], [7,8], [9,0]]")
a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
print(type(a))
b = eval(a)
print(type(b))
print(b)

結果:<class 'str'>
     <class 'list'>
     [[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
字符串轉換成字典b = eval("{1: 'a', 2: 'b'}")
a = "{1: 'a', 2: 'b'}"
print(type(a))
b = eval(a)
print(type(b))
print(b)

結果:<class 'str'>
     <class 'dict'>
     {1: 'a', 2: 'b'}
字符串轉換成元組b = eval("([1,2], [3,4], [5,6], [7,8], (9,0))")
a = "([1,2], [3,4], [5,6], [7,8], (9,0))"
print(type(a))
b = eval(a)
print(type(b))
print(b)

結果:<class 'str'>
   	 <class 'tuple'>
     ([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))

從上邊的例子中可以看出,給eval給個字符串,eval給一個表達式返回值,這就是它的好處

2.eval危險之處

eval雖然方便,但是要注意安全性,可以將字符串轉成表達式並執行,就可以利用執行系統命令,刪除文件等操作。
當使用者不清楚它的危險之處,輸入如下:
eval("__import__('os').system('ls /Users/chunming.liu/Downloads/')")
它其實執行的是如下操作
os.system('ls /Users/chunming.liu/Downloads/')
那么繼續輸入:
eval("__import__('os').system('cat /Users/chunming.liu/Downloads/tls_asimov_cert.pem')")
再來一條刪除命令,文件就會消失。比如
eval("__import__('os').system('rm /Users/chunming.liu/Downloads/車輛轉發測試.png')")
所以使用eval,一方面享受他的了靈活性同時,也要注意安全性。

二、神器2 ——內置函數exec()

python3中刪去了 execfile()方法,使用exec(),它能夠執行復雜的代碼:

with open('test1.py','r') as f:
    exec(f.read())

exec格式語法如下:

exec(object[, globals[, locals]]]
object:必選參數,表示需要被指定的python代碼,它必須是字符串或code對象。如果object是一個字符串,該字符串會被先解析為一組python語句,然后再執行。如果object是一個code對象,那么它只是被簡單的執行
globals:可選參數,同eval函數
locals:可選參數,同eval函數
返回值:
exec函數的返回值永遠為None
globals = {'x': 7, 'y': 10, 'lis': ['aa', 'bb', 'cc']}
locals = {}

a = eval("3*x+4*y", globals, locals)
print(a)

exec("for i in lis:    print(i)", globals, locals)

結果:61
     aa
     bb
     cc

上述示例中exec()中相當於執行了

globals = {'x': 7, 'y': 10, 'lis': ['aa', 'bb', 'cc']}

for i in lis:    
	print(i)

到這里我在跟大家說一下eval()函數與exec()函數的區別:

eval()函數只能計算單個表達式的值,而exec()函數可以動態運行代碼段

eval()函數可以有返回值,而exec()函數返回值永遠為None


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM