python中exec函数修改局部变量
> 前言:本文信息密度很低,是我边研究`exec`边写的# 0. 摘要
本文内容如标题,办法在 4.2
# 1. 引子
代码中碰到一个问题,可简化为:
```python
def calculate(calculate_rule):
account = 0
for c in calculate_rule:
exec('account = 2')
print(account)
```
我以为函数在控制台的输出应该为2,但实际上是0。
# 2. 原因
薅光头发没找到原因,问了一下文心一言,竟然给出了答案:
[!(https://s11.ax1x.com/2024/02/16/pFG6Lzd.png)](https://imgse.com/i/pFG6Lzd)
在代码方面,以前也问过它,但总是没有满意答案,这次倒是让我意外
> 给出的解决办法是错的,后面会提到
# 3. 复现
> 以下部分均为个人推断,如果错误请指出,谢谢
如果我们没有指定`exec`中赋值的变量是全局变量还是局部变量,那么结果总是与我们希望的背道而驰。
## 3.1 exec想给全局变量赋值
### 3.1.1
```python
account = 0
exec(f'account = 2')
print(account)
```
> 输出2,毫无疑问
### 3.1.2
```python
account = 0
def f():
exec(f'account = 2')
print(account)
f()
```
> 输出0,因为`exec`语句中的`account`变量是局部变量,`print`语句中的是全局变量
### 3.1.3
```python
account = 0
def f():
exec(f'account = 2', globals())
print(account)
f()
```
> 输出2,因为`exec`和`print`语句中的`account`变量都是全局变量
## 3.2 exec想给局部变量赋值
### 3.2.1
```python
account = 0
exec(f'account = 2')
print(account)
```
> 输出2,毫无疑问
### 3.2.2
```python
def f():
account = 0
exec(f'account = 2')
print(account)
f()
```
> 输出0,因为`print`语句中是局部变量,而`exec`语句中的`account`变量在全局变量和局部变量中都没有,不知道去哪了
### 3.2.3
```python
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`有关键字参数,所以我改了一下,但是报错:
[!(https://s11.ax1x.com/2024/02/16/pFGRYmn.png)](https://imgse.com/i/pFGRYmn)
向文心一言发送报错内容,回答:
[!(https://s11.ax1x.com/2024/02/16/pFGWkNV.png)](https://imgse.com/i/pFGWkNV)
[!(https://s11.ax1x.com/2024/02/16/pFGWZ3F.png)](https://imgse.com/i/pFGWZ3F)
至此,又碰壁。
## 4.2 询问文心一言
我问`exec`语句中如何修改局部变量,给出如下回答:
[!(https://s11.ax1x.com/2024/02/16/pFGcRk8.png)](https://imgse.com/i/pFGcRk8)
这次给的办法确实有效:
```python
def f():
locals_dict = {'account': 0}# 创建一个字典来存储局部变量
exec('locals_dict["account"] = 2')# 修改字典中的值
account = locals_dict['account']# 更新局部变量
print(account)# 打印修改后的值
f()# 输出: 2
```
> 虽然其中还有一些疑问,而且也不知道文心一言说的还有没有错误,但问题终归是解决了 学习一下 谢谢博主 学习一下,太及时有用了.... exec函数:是个啥 感谢分享,学习一下了!
可是新建的字典是不是也算一个局部变量,为什么不会被修改 奇了怪了,既然你已经有了:
locals_dict["account"] = 2
为什么还要exec 一下呢???原因何在?
wapjsx 发表于 2024-2-17 16:35
奇了怪了,既然你已经有了:
locals_dict["account"] = 2
开头说了,这只是简化后的,实际的代码是这样的:
def calculate(calculate_rule):
local_vars = {'account': 0}
for c in calculate_rule:
try:
exec(f'local_vars["account"] {c}= source_data["{c}"]["{c}"]["account"]')
except Exception as e:
print(e)
return local_vars["account"] MyModHeaven 发表于 2024-2-18 09:04
开头说了,这只是简化后的,实际的代码是这样的:
def calculate(calculate_r ...
{:1_921:}厉害厉害! 膜拜~~~
呵呵,感觉能解决实际问题就好!
页:
[1]