请考虑以下代码:
from sklearn.model_selection import ParameterGrid
def conf1():
return {"p1": [1,2], "p2": [4,5,6]}
def f(aa, bb, cc):
c = locals()
print("CONFIG, locals():")
for k, v, in c.items():
print(f"{k}: {v}")
#>
params = eval("conf1()")
grid = ParameterGrid(params)
#<
d = {**c}
print("CONF after eval")
for k, v, in d.items():
print(f"{k}: {v}")
f(1,2,3)
其输出为:
CONFIG, locals():
aa: 1
bb: 2
cc: 3
CONF after eval
aa: 1
bb: 2
cc: 3
c: {'aa': 1, 'bb': 2, 'cc': 3, 'c': {...}, 'k': 'cc', 'v': 3}
k: cc
v: 3
函数f
使用其局部名称,特别是其接收的参数,创建字典c
.然后由eval("conf1()")
创建一个新词典.然后,创建一个d = {**c}
.
似乎当执行c = {**d}
时,d = locals()
被重新判断.因为在这一点上,本地环境也包含k
、v
和d
,它们最终会变成d
.如果我删除eval
(#>
和#<
之间的行),我会得到我所期望的,即c
和d
包含相同的项.
可能不是因为eval,但我真的无法理解发生了什么.我找不到任何解释.有什么帮助吗?
因为我在 comments 中读到config
是可变"locals()"的名称,所以我做了这个测试:
def f(param1, param2):
config = locals()
print("1. config:")
for k, v in config.items():
print(f"- {k}: {v}")
name =1
print("2. config:")
for k, v in config.items():
print(f"- {k}: {v}")
f(1, 2)
带输出:
1. config:
- param2: 2
- param1: 1
2. config:
- param2: 2
- param1: 1
所以它似乎不那么易变.
如果加上eval
:
def f(param1, param2):
config = locals()
print("1. config:")
for k, v in config.items():
print(f"- {k}: {v}")
name = 1
eval("print()")
print("2. config:")
for k, v in config.items():
print(f"- {k}: {v}")
f(1, 2)
再一次:
1. config:
- param2: 2
- param1: 1
2. config:
- param2: 2
- param1: 1
- name: 1
- v: 1
- k: param1
- config: {'param2': 2, 'param1': 1, 'name': 1, 'v': 1, 'k': 'param1', 'config': {...}}
在@juanpa的 comments 之后.arrivillaga,我得到了它,并且能够在没有eval()
的情况下复制:
def f(param1, param2):
config = locals()
print("1. config:")
for k, v in config.items():
print(f"- {k}: {v}")
name = "hello"
locals()
print("2. config:")
for k, v in config.items():
print(f"- {k}: {v}")
f(1, 2)
带输出:
1. config:
- param2: 2
- param1: 1
2. config:
- param2: 2
- param1: 1
- name: hello
- v: 1
- k: param1
- config: {'param2': 2, 'param1': 1, 'name': 'hello', 'v': 1, 'k': 'param1', 'config': {...}}
文件中说:
locals()更新并返回表示当前本地
我会用"…还字典…"而不是"a",但无论如何...
谢谢大家.
对于将来访问此页面的用户.在阅读了权威来源的示例后,我开始使用config=locals()
来保存一个类似配置的字典,但该赋值并不"正确",并导致这些奇怪的行为,在复杂的代码中很难发现.
使用locals()
保存配置字典的更好方法是config = {**locals()}
:
def f(param1, param2):
config = {**locals()}
print("1. config:")
for k, v in config.items():
print(f"- {k}: {v}")
name = "hello"
locals()
print("2. config:")
for k, v in config.items():
print(f"- {k}: {v}")
f(1, 2)
对于预期的正常行为,尤其是对于习惯于使用变量而不是名称的语言的人:
1. config:
- param2: 2
- param1: 1
2. config:
- param2: 2
- param1: 1
我同意公认答案的作者:文档应该更接近实际语义.