前言:本文信息密度很低,是我边研究exec
边写的
0. 摘要
本文内容如标题,办法在 4.2
1. 引子
代码中碰到一个问题,可简化为:
def calculate(calculate_rule):
account = 0
for c in calculate_rule:
exec('account = 2')
print(account)
我以为函数在控制台的输出应该为2,但实际上是0。
2. 原因
薅光头发没找到原因,问了一下文心一言,竟然给出了答案:
在代码方面,以前也问过它,但总是没有满意答案,这次倒是让我意外
给出的解决办法是错的,后面会提到
3. 复现
以下部分均为个人推断,如果错误请指出,谢谢
如果我们没有指定exec
中赋值的变量是全局变量还是局部变量,那么结果总是与我们希望的背道而驰。
3.1 exec想给全局变量赋值
3.1.1
account = 0
exec(f'account = 2')
print(account)
输出2,毫无疑问
3.1.2
account = 0
def f():
exec(f'account = 2')
print(account)
f()
输出0,因为exec
语句中的account
变量是局部变量,print
语句中的是全局变量
3.1.3
account = 0
def f():
exec(f'account = 2', globals())
print(account)
f()
输出2,因为exec
和print
语句中的account
变量都是全局变量
3.2 exec想给局部变量赋值
3.2.1
account = 0
exec(f'account = 2')
print(account)
输出2,毫无疑问
3.2.2
def f():
account = 0
exec(f'account = 2')
print(account)
f()
输出0,因为print
语句中是局部变量,而exec
语句中的account
变量在全局变量和局部变量中都没有,不知道去哪了
3.2.3
def f():
account = 0
exec(f'account = 2', globals(), locals())
print(account)
f()
如文心一言所言,这时候输出的应该是局部变量account
,值为2,但实际上输出的值还是0。所以它说错了
4. 纠错
4.1 自行修改
https://docs.python.org/zh-cn/3/library/functions.html#exec
看到官方文档,exec(object, globals=None, locals=None, /, *, closure=None)
,exec
有关键字参数,所以我改了一下,但是报错:
向文心一言发送报错内容,回答:
至此,又碰壁。
4.2 询问文心一言
我问exec
语句中如何修改局部变量,给出如下回答:
这次给的办法确实有效:
def f():
locals_dict = {'account': 0} # 创建一个字典来存储局部变量
exec('locals_dict["account"] = 2') # 修改字典中的值
account = locals_dict['account'] # 更新局部变量
print(account) # 打印修改后的值
f() # 输出: 2
虽然其中还有一些疑问,而且也不知道文心一言说的还有没有错误,但问题终归是解决了