Python 在局部變量域中執(zhí)行代碼
問題
你想在使用范圍內(nèi)執(zhí)行某個代碼片段,并且希望在執(zhí)行后所有的結(jié)果都不可見。
解決方案
為了理解這個問題,先試試一個簡單場景。首先,在全局命名空間內(nèi)執(zhí)行一個代碼片段:
>>> a = 13 >>> exec('b = a + 1') >>> print(b) 14 >>>
然后,再在一個函數(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 >>>
可以看出,最后拋出了一個NameError異常,就跟在 exec()
語句從沒執(zhí)行過一樣。 要是你想在后面的計算中使用到 exec()
執(zhí)行結(jié)果的話就會有問題了。
為了修正這樣的錯誤,你需要在調(diào)用 exec()
之前使用 locals()
函數(shù)來得到一個局部變量字典。 之后你就能從局部字典中獲取修改過后的變量值了。例如:
>>> def test(): ... a = 13 ... loc = locals() ... exec('b = a + 1') ... b = loc['b'] ... print(b) ... >>> test() 14 >>>
討論
實際上對于 exec()
的正確使用是比較難的。大多數(shù)情況下當(dāng)你要考慮使用 exec()
的時候, 還有另外更好的解決方案(比如裝飾器、閉包、元類等等)。
然而,如果你仍然要使用 exec() ,本節(jié)列出了一些如何正確使用它的方法。 默認情況下,exec() 會在調(diào)用者局部和全局范圍內(nèi)執(zhí)行代碼。然而,在函數(shù)里面, 傳遞給 exec() 的局部范圍是拷貝實際局部變量組成的一個字典。 因此,如果 exec() 如果執(zhí)行了修改操作,這種修改后的結(jié)果對實際局部變量值是沒有影響的。 下面是另外一個演示它的例子:
>>> def test1(): ... x = 0 ... exec('x += 1') ... print(x) ... >>> test1() 0 >>>
上面代碼里,當(dāng)你調(diào)用 locals()
獲取局部變量時,你獲得的是傳遞給 exec()
的局部變量的一個拷貝。 通過在代碼執(zhí)行后審查這個字典的值,那就能獲取修改后的值了。下面是一個演示例子:
>>> 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 >>>
仔細觀察最后一步的輸出,除非你將 loc 中被修改后的值手動賦值給x,否則x變量值是不會變的。
在使用 locals()
的時候,你需要注意操作順序。每次它被調(diào)用的時候, locals()
會獲取局部變量值中的值并覆蓋字典中相應(yīng)的變量。 請注意觀察下下面這個試驗的輸出結(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()
的時候x的值是如何被覆蓋掉的。
作為 locals()
的一個替代方案,你可以使用你自己的字典,并將它傳遞給 exec()
。例如:
>>> def test4(): ... a = 13 ... loc = { 'a' : a } ... glb = { } ... exec('b = a + 1', glb, loc) ... b = loc['b'] ... print(b) ... >>> test4() 14 >>>
大部分情況下,這種方式是使用 exec()
的最佳實踐。 你只需要保證全局和局部字典在后面代碼訪問時已經(jīng)被初始化。
還有一點,在使用 exec()
之前,你可能需要問下自己是否有其他更好的替代方案。 大多數(shù)情況下當(dāng)你要考慮使用 exec()
的時候, 還有另外更好的解決方案,比如裝飾器、閉包、元類,或其他一些元編程特性。
以上就是Python 在局部變量域中執(zhí)行代碼的詳細內(nèi)容,更多關(guān)于Python 局部變量域的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python實現(xiàn)對桌面進行實時捕捉畫面的方法詳解
最近在研究目標檢測方面的小東西,需要到對桌面進行實時捕捉畫面。所以本文來用Python實現(xiàn)簡單的對桌面進行實時捕捉畫面,感興趣的可以了解一下2023-01-01Python調(diào)用系統(tǒng)命令的四種方法詳解(os.system、os.popen、commands、subprocess)
這篇文章主要介紹了Python調(diào)用系統(tǒng)命令的四種方法(os.system、os.popen、commands、subprocess),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03PyTorch中tensor.backward()函數(shù)的詳細介紹及功能實現(xiàn)
backward()?函數(shù)是PyTorch框架中自動求梯度功能的一部分,它負責(zé)執(zhí)行反向傳播算法以計算模型參數(shù)的梯度,這篇文章主要介紹了PyTorch中tensor.backward()函數(shù)的詳細介紹,需要的朋友可以參考下2024-02-02Python找出列表中出現(xiàn)次數(shù)最多的元素三種方式
本文通過三種方式給大家介紹Python找出列表中出現(xiàn)次數(shù)最多的元素,每種方式通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友參考下2020-02-02Python+OpenCV實現(xiàn)信用卡數(shù)字識別的方法詳解
這篇文章主要介紹了如何利用python?opencv實現(xiàn)信用卡數(shù)字識別,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09