python中關(guān)于eval函數(shù)的使用及說明

  • A+
所屬分類:百科知識

eval是Python的一個(gè)內(nèi)置函數(shù),功能十分強(qiáng)大,這個(gè)函數(shù)的作用是,返回傳入字符串的表達(dá)式的結(jié)果。

就是說:將字符串當(dāng)成有效的表達(dá)式 來求值 并 返回計(jì)算結(jié)果。

eval函數(shù)就是實(shí)現(xiàn)list、dict、tuple與str之間的轉(zhuǎn)化,同樣str函數(shù)把list,dict,tuple轉(zhuǎn)為為字符串

1.eval的語法

1
eval(expression[, globals[, locals]])
  • expression?: 表達(dá)式。
  • globals?: (可選參數(shù))變量作用域,全局命名空間,如果被提供,則必須是一個(gè)字典對象。
  • locals?: (可選參數(shù))變量作用域,局部命名空間,如果被提供,可以是任何映射對象。

既然eval有兩個(gè)可選參數(shù)是命名空間,那么先搞清楚啥是命名空間吧?

2.命名空間

定義

名稱到對象的映射。python是用命名空間來記錄變量的軌跡的,命名空間是一個(gè)dictionary,鍵是變量名,值是變量值。各個(gè)命名空間是獨(dú)立沒有關(guān)系的,一個(gè)命名空間中不能有重名,但是不同的命名空間可以重名而沒有任何影響。

分類

python程序執(zhí)行期間會有2個(gè)或3個(gè)活動的命名空間(函數(shù)調(diào)用時(shí)有3個(gè),函數(shù)調(diào)用結(jié)束后2個(gè))。按照變量定義的位置,可以劃分為以下3類:

  • Local,局部命名空間,每個(gè)函數(shù)所擁有的命名空間,記錄了函數(shù)中定義的所有變量,包括函數(shù)的入?yún)ⅰ?nèi)部定義的局部變量。
  • Global,全局命名空間,每個(gè)模塊加載執(zhí)行時(shí)創(chuàng)建的,記錄了模塊中定義的變量,包括模塊中定義的函數(shù)、類、其他導(dǎo)入的模塊、模塊級的變量與常量。
  • Built-in,python自帶的內(nèi)建命名空間,任何模塊均可以訪問,放著內(nèi)置的函數(shù)和異常。

生命周期

  • Local(局部命名空間)在函數(shù)被調(diào)用時(shí)才被創(chuàng)建,但函數(shù)返回結(jié)果或拋出異常時(shí)被刪除。(每一個(gè)遞歸函數(shù)都擁有自己的命名空間)。
  • Global(全局命名空間)在模塊被加載時(shí)創(chuàng)建,通常一直保留直到python解釋器退出。
  • Built-in(內(nèi)建命名空間)在python解釋器啟動時(shí)創(chuàng)建,一直保留直到解釋器退出。

各命名空間創(chuàng)建順序:

python解釋器啟動 ->創(chuàng)建內(nèi)建命名空間 -> 加載模塊 -> 創(chuàng)建全局命名空間 ->函數(shù)被調(diào)用 ->創(chuàng)建局部命名空間

各命名空間銷毀順序:

函數(shù)調(diào)用結(jié)束 -> 銷毀函數(shù)對應(yīng)的局部命名空間 -> python虛擬機(jī)(解釋器)退出 ->銷毀全局命名空間 ->銷毀內(nèi)建命名空間

python解釋器加載階段會創(chuàng)建出內(nèi)建命名空間、模塊的全局命名空間,局部命名空間是在運(yùn)行階段函數(shù)被調(diào)用時(shí)動態(tài)創(chuàng)建出來的,函數(shù)調(diào)用結(jié)束動態(tài)的銷毀的。

python的全局命名空間存儲在一個(gè)叫g(shù)lobals()的dict對象中;局部命名空間存儲在一個(gè)叫l(wèi)ocals()的dict對象中。

可以用print (locals())來查看該函數(shù)體內(nèi)的所有變量名和變量值。

1
2
3
4
5
6
print(locals()) ?#打印顯示所有的局部變量
'''
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001B22E13B128>,
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/pythoyworkspace/file_demo/Class_Demo/pachong/urllib_Request1.py',
'__cached__': None, 's': '1+2+3*5-2', 'x': 1, 'age': 18}
Process finished with exit code 0

3.參數(shù)查找

當(dāng)后兩個(gè)參數(shù)都為空時(shí),很好理解,就是一個(gè)string類型的算術(shù)表達(dá)式,計(jì)算出結(jié)果即可。等價(jià)于eval(expression)。

當(dāng)locals參數(shù)為空,globals參數(shù)不為空時(shí),先查找globals參數(shù)中是否存在變量,并計(jì)算。

當(dāng)兩個(gè)參數(shù)都不為空時(shí),先查找locals參數(shù),再查找globals參數(shù)。

4.eval的使用演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#1.eval無參實(shí)現(xiàn)字符串轉(zhuǎn)化
s = '1+2+3*5-2'
print(eval(s)) ?#16
#2.字符串中有變量也可以
x = 1
print(eval('x+2')) ?#3
#3.字符串轉(zhuǎn)字典
print(eval("{'name':'linux','age':18}"))
#輸出結(jié)果:{'name':'linux','age':18}
#4.eval傳遞全局變量參數(shù),注意字典里的:age中的age沒有帶引號,說明它是個(gè)變量,而不是字符串。
#這里兩個(gè)參數(shù)都是全局的
print(eval("{'name':'linux','age':age}",{"age":1822}))
#輸出結(jié)果:{'name': 'linux', 'age': 1822}
print(eval("{'name':'linux','age':age}",{"age":1822},{"age":1823}))
#輸出結(jié)果:{'name': 'linux', 'age': 1823}
#eval傳遞本地變量,既有g(shù)lobal和local時(shí),變量值先從local中查找。
age=18
print(eval("{'name':'linux','age':age}",{"age":1822},locals()))
#輸出結(jié)果:{'name': 'linux', 'age': 18}
print("-----------------")
print(eval("{'name':'linux','age':age}"))

5.eval的使用與風(fēng)險(xiǎn)

python3中input將接受的結(jié)果存為字符串,一般來說,可以使用eval實(shí)現(xiàn)表達(dá)式的還原,并且實(shí)現(xiàn)表達(dá)式的計(jì)算

比如下面使用eval直接完成了表達(dá)式的還原與計(jì)算:

1
2
3
4
5
>>> s = input("輸入一個(gè)表達(dá)式")
輸入一個(gè)表達(dá)式:1+3+4+4*3
>>> print(eval(s))
20
>>>

eval雖然方便,但是要注意安全性,可以將字符串轉(zhuǎn)成表達(dá)式并執(zhí)行,就可以利用執(zhí)行系統(tǒng)命令,刪除文件等操作。

比如用戶惡意輸入就會獲得當(dāng)前目錄文件

>>>eval("__import__('os').system('dir')")
驅(qū)動器 C 中的卷是 OS
卷的序列號是 B234-8A38

C:\Users\Robot_TENG 的目錄

2019-07-01 ?09:11 ? ?<DIR> ? ? ? ? ?.
2019-07-01 ?09:11 ? ?<DIR> ? ? ? ? ?..
2017-11-23 ?16:15 ? ?<DIR> ? ? ? ? ?.android
2018-12-23 ?00:02 ? ?<DIR> ? ? ? ? ?.conda
2018-12-06 ?19:08 ? ? ? ? ? ? ? ?20 .dbshell
2017-12-01 ?19:28 ? ?<DIR> ? ? ? ? ?.eclipse
2018-01-22 ?22:46 ? ?<DIR> ? ? ? ? ?.idea-build
2017-12-31 ?14:49 ? ?<DIR> ? ? ? ? ?.IdeaIC2017.1
2018-01-22 ?21:21 ? ?<DIR> ? ? ? ? ?.IdeaIC2017.2
2019-07-01 ?09:11 ? ?<DIR> ? ? ? ? ?.ipynb_checkpoints
2018-12-19 ?20:04 ? ?<DIR> ? ? ? ? ?.ipython
2019-07-01 ?09:30 ? ?<DIR> ? ? ? ? ?.jupyter
2017-12-01 ?16:11 ? ?<DIR> ? ? ? ? ?.m2
2017-12-31 ?23:14 ? ? ? ? ? ? ? ? 0 .mongorc.js
2019-02-03 ?22:52 ? ?<DIR> ? ? ? ? ?.p2
2018-07-16 ?22:04 ? ?<DIR> ? ? ? ? ?.PyCharm2016.1
2018-12-06 ?19:49 ? ?<DIR> ? ? ? ? ?.rdm
2018-01-22 ?22:09 ? ? ? ? ? ? ? 580 .scala_history
2018-12-06 ?19:19 ? ?<DIR> ? ? ? ? ?.vscode
2019-06-21 ?16:37 ? ?<DIR> ? ? ? ? ?3D Objects
2019-06-21 ?16:37 ? ?<DIR> ? ? ? ? ?Contacts
2019-07-01 ?16:21 ? ?<DIR> ? ? ? ? ?Desktop
2019-06-28 ?16:34 ? ?<DIR> ? ? ? ? ?Documents
2019-06-28 ?10:26 ? ?<DIR> ? ? ? ? ?Downloads
2018-09-11 ?22:24 ? ?<DIR> ? ? ? ? ?Evernote
2019-06-21 ?16:37 ? ?<DIR> ? ? ? ? ?Favorites
2018-08-02 ?23:58 ? ?<DIR> ? ? ? ? ?HBuilder
2018-08-03 ?00:00 ? ?<DIR> ? ? ? ? ?HBuilder settings
2018-08-03 ?00:02 ? ?<DIR> ? ? ? ? ?HBuilderProjects
2019-06-21 ?16:37 ? ?<DIR> ? ? ? ? ?Links
2019-06-21 ?16:37 ? ?<DIR> ? ? ? ? ?Music
2018-03-18 ?00:22 ? ?<DIR> ? ? ? ? ?Oracle
2019-06-21 ?16:37 ? ?<DIR> ? ? ? ? ?Pictures
2019-06-21 ?16:37 ? ?<DIR> ? ? ? ? ?Saved Games
2019-06-21 ?16:37 ? ?<DIR> ? ? ? ? ?Searches
2018-12-23 ?00:47 ? ? ? ? ? ? ? 690 Untitled.ipynb
2019-07-01 ?09:11 ? ? ? ? ? ? ? ?72 Untitled1.ipynb
2019-06-30 ?18:43 ? ?<DIR> ? ? ? ? ?Videos
2019-01-13 ?18:20 ? ?<DIR> ? ? ? ? ?Yinxiang Biji
5 個(gè)文件 ? ? ? ? ?1,362 字節(jié)
34 個(gè)目錄 72,365,862,912 可用字節(jié)

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考

推薦應(yīng)用

發(fā)表評論

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: