[英]scope of globals, locals, use with exec()
我很難理解 Python 中的globals()
和locals()
的 scope。請考慮以下代碼:
def f1(glob, loc):
exec("b = 5", glob, loc)
f1(globals(), locals())
print(b + 1)
這會將globals
和locals
變量傳遞給定義了變量b = 5
的f1
,並且在主 scope 中的 function 調用之后確實存在。代碼正確打印
6
令我驚訝的是,當在 function 的 scope 中執行相同操作時, f2
在這里失敗了:
def f1(glob, loc):
exec("b = 5", glob, loc)
def f2():
f1(globals(), locals())
print(b + 1)
f2()
Traceback (most recent call last):
File "/tmp/q.py", line 10, in <module>
f2()
File "/tmp/q.py", line 7, in f2
print(b + 1)
NameError: name 'b' is not defined
這是為什么? 是否可以泛化f1
以允許從f2
調用它?
在您的第一個示例中, locals
是globals
字典,因為您處於模塊級別。
您可以使用print(id(globals()), id(locals()))
檢查
在您的第二個示例中, locals
是 function 的 scope 中的不同字典。
因此,要使示例 2 工作,請使用:
def f1(glob, loc):
exec("b = 5", glob, loc)
def f2():
f1(globals(), globals())
print(b + 1)
f2()
或者
def f1(glob, loc):
exec("b = 5", glob, glob)
def f2(loc):
f1(globals(), loc)
print(b + 1)
f2(locals())
所以這實際上不是exec()
的問題,而是您在其中調用locals()
的 scope 的問題。
而且這也是 exec 中的代碼做什么的問題,因為賦值會將名稱的 scope 更改為當前(本地)scope,除非涉及global
/ nonlocal
。 這就是為什么b=5
在本地 scope 中執行的原因——除了在您的第一個示例中,“本地”scope 是全局scope。
跟進:
如果你想在f2
中為b
重新分配一個值,你將需要global
關鍵字:
def f1(glob, loc):
exec("b = 5", glob, loc)
def f2():
f1(globals(), globals())
global b
b += 1
print(b + 1) # 7
f2()
請注意,這與 exec 和傳遞 locals() / globals() 無關 - 您可以將其簡化為這個示例,如果沒有global
關鍵字,它也會失敗(它會拋出UnboundLocalError: local variable 'b' referenced before assignment
)。
b = 5
def f2():
global b
b += 1
print(b + 1) # 7
f2()
這不是一個解釋性答案(傑森的評論似乎是一個很好的答案),但在工作中我編寫了一些使用exec
的代碼,我發現exec(code, globals())
是唯一有效的方法在任何情況下。 添加本地人作為參數只會導致各種問題。
調整您的代碼:
def f1(glob):
exec("b = 5", glob)
def f2():
f1(globals())
print(b + 1)
f2()
# 6
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.