Python 在局部變量域中執(zhí)行代碼
問題
你想在使用范圍內(nèi)執(zhí)行某個(gè)代碼片段,并且希望在執(zhí)行后所有的結(jié)果都不可見。
解決方案
為了理解這個(gè)問題,先試試一個(gè)簡單場景。首先,在全局命名空間內(nèi)執(zhí)行一個(gè)代碼片段:
>>> a = 13
>>> exec('b = a + 1')
>>> print(b)
14
>>>
然后,再在一個(gè)函數(shù)中執(zhí)行同樣的代碼:
>>> def test():
... a = 13
... exec('b = a + 1')
... print(b)
...
>>> test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in test
NameError: global name 'b' is not defined
>>>
可以看出,最后拋出了一個(gè)NameError異常,就跟在 exec() 語句從沒執(zhí)行過一樣。 要是你想在后面的計(jì)算中使用到 exec() 執(zhí)行結(jié)果的話就會有問題了。
為了修正這樣的錯(cuò)誤,你需要在調(diào)用 exec() 之前使用 locals() 函數(shù)來得到一個(gè)局部變量字典。 之后你就能從局部字典中獲取修改過后的變量值了。例如:
>>> def test():
... a = 13
... loc = locals()
... exec('b = a + 1')
... b = loc['b']
... print(b)
...
>>> test()
14
>>>
討論
實(shí)際上對于 exec() 的正確使用是比較難的。大多數(shù)情況下當(dāng)你要考慮使用 exec() 的時(shí)候, 還有另外更好的解決方案(比如裝飾器、閉包、元類等等)。
然而,如果你仍然要使用 exec() ,本節(jié)列出了一些如何正確使用它的方法。 默認(rèn)情況下,exec() 會在調(diào)用者局部和全局范圍內(nèi)執(zhí)行代碼。然而,在函數(shù)里面, 傳遞給 exec() 的局部范圍是拷貝實(shí)際局部變量組成的一個(gè)字典。 因此,如果 exec() 如果執(zhí)行了修改操作,這種修改后的結(jié)果對實(shí)際局部變量值是沒有影響的。 下面是另外一個(gè)演示它的例子:
>>> def test1():
... x = 0
... exec('x += 1')
... print(x)
...
>>> test1()
0
>>>
上面代碼里,當(dāng)你調(diào)用 locals() 獲取局部變量時(shí),你獲得的是傳遞給 exec() 的局部變量的一個(gè)拷貝。 通過在代碼執(zhí)行后審查這個(gè)字典的值,那就能獲取修改后的值了。下面是一個(gè)演示例子:
>>> def test2():
... x = 0
... loc = locals()
... print('before:', loc)
... exec('x += 1')
... print('after:', loc)
... print('x =', x)
...
>>> test2()
before: {'x': 0}
after: {'loc': {...}, 'x': 1}
x = 0
>>>
仔細(xì)觀察最后一步的輸出,除非你將 loc 中被修改后的值手動賦值給x,否則x變量值是不會變的。
在使用 locals() 的時(shí)候,你需要注意操作順序。每次它被調(diào)用的時(shí)候, locals() 會獲取局部變量值中的值并覆蓋字典中相應(yīng)的變量。 請注意觀察下下面這個(gè)試驗(yàn)的輸出結(jié)果:
>>> def test3():
... x = 0
... loc = locals()
... print(loc)
... exec('x += 1')
... print(loc)
... locals()
... print(loc)
...
>>> test3()
{'x': 0}
{'loc': {...}, 'x': 1}
{'loc': {...}, 'x': 0}
>>>
>>> def test3():
... x = 0
... loc = locals()
... print(loc)
... exec('x += 1')
... print(loc)
... locals()
... print(loc)
...
>>> test3()
{'x': 0}
{'loc': {...}, 'x': 1}
{'loc': {...}, 'x': 0}
>>>
注意最后一次調(diào)用 locals() 的時(shí)候x的值是如何被覆蓋掉的。
作為 locals() 的一個(gè)替代方案,你可以使用你自己的字典,并將它傳遞給 exec() 。例如:
>>> def test4():
... a = 13
... loc = { 'a' : a }
... glb = { }
... exec('b = a + 1', glb, loc)
... b = loc['b']
... print(b)
...
>>> test4()
14
>>>
大部分情況下,這種方式是使用 exec() 的最佳實(shí)踐。 你只需要保證全局和局部字典在后面代碼訪問時(shí)已經(jīng)被初始化。
還有一點(diǎn),在使用 exec() 之前,你可能需要問下自己是否有其他更好的替代方案。 大多數(shù)情況下當(dāng)你要考慮使用 exec() 的時(shí)候, 還有另外更好的解決方案,比如裝飾器、閉包、元類,或其他一些元編程特性。
以上就是Python 在局部變量域中執(zhí)行代碼的詳細(xì)內(nèi)容,更多關(guān)于Python 局部變量域的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
導(dǎo)入tensorflow:ImportError: libcublas.so.9.0 報(bào)錯(cuò)
這篇文章主要介紹了導(dǎo)入tensorflow:ImportError: libcublas.so.9.0 報(bào)錯(cuò),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
Python使用Matplotlib庫創(chuàng)建3D 圖形和交互式圖形詳解
Matplotlib 是 Python 中最重要的數(shù)據(jù)可視化庫之一,在本文中,我們將深入研究 Matplotlib 的高級特性,特別是如何創(chuàng)建 3D 圖形和交互式圖形,需要的朋友可以參考下2023-07-07
pandas如何實(shí)現(xiàn)兩個(gè)dataframe相減
這篇文章主要介紹了pandas如何實(shí)現(xiàn)兩個(gè)dataframe相減方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02
解決CentOS下ImportError: No module named &a
這篇文章主要介紹了解決CentOS下ImportError: No module named '_sqlite3'的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12

