为什么 exec() 函数在原始代码中有效,但在 Python 3.7 中的函数或 class 中无效?
Why dows exec() function work in raw code but not within a function or a class in Python 3.7?
下面我展示了 Python 3.7 中 exec() 函数的 2 个用法示例,一个在 class 中,一个在原始代码中。只有后者才能正常工作。有人可以向我解释可能的原因并提出解决方案吗?
#!/usr/bin/env python
import pandas as pd
################################# exec() WITHIN A CLASS ###################################
class Test:
def __init__(self):
pass
def f(self):
pose, frame, min_complexE, min_lEfree, best_structvar, best_conf, complexE, ligandE_bound, proteinE_bound, \
min_lEfree = [None] * 10
table = pd.read_table("sample_scores.txt", delim_whitespace=True, skiprows=[0]) # 1st line is a comment
table_columns = table.columns
for i, row in table.iterrows():
# Variable assignemnt
for varname in ["pose", "frame", "min_complexE", "min_lEfree", "best_structvar", "best_conf",
"complexE", "ligandE_bound", "proteinE_bound", "min_lEfree", "Eint"]:
if varname in table_columns:
exec("%s = %s" % (varname, row[varname]), globals(), globals())
else:
exec("%s = None" % (varname), globals(), globals())
print("proteinE_bound within class =", proteinE_bound)
def caller1(self):
self.f()
def caller2(self):
self.caller1()
Test().caller2()
################################# exec() IN RAW CODE ###################################
pose, frame, min_complexE, min_lEfree, best_structvar, best_conf, complexE, ligandE_bound, proteinE_bound, \
min_lEfree = [None] * 10
table = pd.read_table("sample_scores.txt", delim_whitespace=True, skiprows=[0]) # 1st line is a comment
table_columns = table.columns
for i, row in table.iterrows():
# Variable assignemnt
for varname in ["pose", "frame", "min_complexE", "min_lEfree", "best_structvar", "best_conf",
"complexE", "ligandE_bound", "proteinE_bound", "min_lEfree", "Eint"]:
if varname in table_columns:
exec("%s = %s" % (varname, row[varname]), globals(), globals())
else:
exec("%s = None" % (varname), globals(), globals())
print("proteinE_bound as raw code =", proteinE_bound)
"sample_scores.txt" 文件的内容是:
# Contains all results. For the best result for each compound please refer to file BEST_RESULTS.
molname Eint complexE ligandE_bound proteinE_bound stereoisomer ionstate tautomer pose frame
LEM00001847 -63.000496 -17406.593934 -84.868633 -17258.724804 1 1 1 1 571
LEM00001847 -62.412897 -17474.918135 -64.778724 -17347.726515 1 1 1 1 171
LEM00001847 -61.249384 -17423.452346 -82.875735 -17279.327226 1 1 1 1 531
我找到了答案,虽然其中还有一些晦涩难懂的地方。基本上,我不得不删除行
pose, frame, min_complexE, min_lEfree, best_structvar, best_conf, complexE, ligandE_bound, proteinE_bound, \
min_lEfree = [None] * 10
我在这里初始化了要由 exec() 分配的变量。如果这些变量不预先存在,那么它们将成功添加到 globals() 并且可以在函数中作为单独的变量访问。
现在难点:
1) 即使我将这 10 个变量初始化为 None,在 for 循环的每次迭代中,它们的值都会在 globals() 字典中更新,但当我将它们的名称作为单个变量调用 then 时则不会。
2) 根据docs.python.org exec(__object, __globals=..., __locals=...)
。似乎只有给定的 '__globals' 字典会用新变量更新。所以虽然在我上面的代码中我使用
exec("%s = %s" % (varname, row[varname]), globals(), globals())
这也行
exec("%s = %s" % (varname, row[varname]), locals(), globals())
以我的理解,后者是正确的方式,因为你希望这些变量在函数的上下文中创建,即作为局部变量。但是为什么 exec() 更新给定的 '__globals' 而不是给定的 '__locals'?
下面我展示了 Python 3.7 中 exec() 函数的 2 个用法示例,一个在 class 中,一个在原始代码中。只有后者才能正常工作。有人可以向我解释可能的原因并提出解决方案吗?
#!/usr/bin/env python
import pandas as pd
################################# exec() WITHIN A CLASS ###################################
class Test:
def __init__(self):
pass
def f(self):
pose, frame, min_complexE, min_lEfree, best_structvar, best_conf, complexE, ligandE_bound, proteinE_bound, \
min_lEfree = [None] * 10
table = pd.read_table("sample_scores.txt", delim_whitespace=True, skiprows=[0]) # 1st line is a comment
table_columns = table.columns
for i, row in table.iterrows():
# Variable assignemnt
for varname in ["pose", "frame", "min_complexE", "min_lEfree", "best_structvar", "best_conf",
"complexE", "ligandE_bound", "proteinE_bound", "min_lEfree", "Eint"]:
if varname in table_columns:
exec("%s = %s" % (varname, row[varname]), globals(), globals())
else:
exec("%s = None" % (varname), globals(), globals())
print("proteinE_bound within class =", proteinE_bound)
def caller1(self):
self.f()
def caller2(self):
self.caller1()
Test().caller2()
################################# exec() IN RAW CODE ###################################
pose, frame, min_complexE, min_lEfree, best_structvar, best_conf, complexE, ligandE_bound, proteinE_bound, \
min_lEfree = [None] * 10
table = pd.read_table("sample_scores.txt", delim_whitespace=True, skiprows=[0]) # 1st line is a comment
table_columns = table.columns
for i, row in table.iterrows():
# Variable assignemnt
for varname in ["pose", "frame", "min_complexE", "min_lEfree", "best_structvar", "best_conf",
"complexE", "ligandE_bound", "proteinE_bound", "min_lEfree", "Eint"]:
if varname in table_columns:
exec("%s = %s" % (varname, row[varname]), globals(), globals())
else:
exec("%s = None" % (varname), globals(), globals())
print("proteinE_bound as raw code =", proteinE_bound)
"sample_scores.txt" 文件的内容是:
# Contains all results. For the best result for each compound please refer to file BEST_RESULTS.
molname Eint complexE ligandE_bound proteinE_bound stereoisomer ionstate tautomer pose frame
LEM00001847 -63.000496 -17406.593934 -84.868633 -17258.724804 1 1 1 1 571
LEM00001847 -62.412897 -17474.918135 -64.778724 -17347.726515 1 1 1 1 171
LEM00001847 -61.249384 -17423.452346 -82.875735 -17279.327226 1 1 1 1 531
我找到了答案,虽然其中还有一些晦涩难懂的地方。基本上,我不得不删除行
pose, frame, min_complexE, min_lEfree, best_structvar, best_conf, complexE, ligandE_bound, proteinE_bound, \
min_lEfree = [None] * 10
我在这里初始化了要由 exec() 分配的变量。如果这些变量不预先存在,那么它们将成功添加到 globals() 并且可以在函数中作为单独的变量访问。
现在难点:
1) 即使我将这 10 个变量初始化为 None,在 for 循环的每次迭代中,它们的值都会在 globals() 字典中更新,但当我将它们的名称作为单个变量调用 then 时则不会。
2) 根据docs.python.org exec(__object, __globals=..., __locals=...)
。似乎只有给定的 '__globals' 字典会用新变量更新。所以虽然在我上面的代码中我使用
exec("%s = %s" % (varname, row[varname]), globals(), globals())
这也行
exec("%s = %s" % (varname, row[varname]), locals(), globals())
以我的理解,后者是正确的方式,因为你希望这些变量在函数的上下文中创建,即作为局部变量。但是为什么 exec() 更新给定的 '__globals' 而不是给定的 '__locals'?