exec(variable =)在for循环中分配的变量范围?
Scope of variables assigned by exec(variable =) in a for loop?
我知道大多数人不喜欢使用 exec 进行动态分配。但是,出于我的目的(务实和古怪),我想将变量名称视为数据。
考虑这个例子,我在 class 初始化期间使用它
现在我要给这些变量动态赋值
class Example(object):
__tree_dict = {"self.genomedir": "genomes",
"self.pre_align": "pre_alignment",
"self.alignments": "alignments",
"self.trimmed": "trimmed",
"self.prf_pre": "prf_preprocess",
"self.scaled": "scaled",
"self.csv": "csv"}
def __init__(self, rootdir):
self._rootdir = Path(rootdir)
self.outdir = self.mksubdir(self._rootdir, "out")
for variable, human_readable in self.__tree_dict.items():
try:
exec(variable + " = self.mksubdir(self.outdir,human_readable)")
except:
LOGGER.error("%s failed to initialize as %s, defaulting output to root" (variable, human_readable), exc_info=True)
exec(variable + '= Path(self._rootdir)')
这段代码会运行,但我不确定异常处理是否真的有效,因为当我添加一个 finally 语句将变量赋值写入记录器时,例如
finally:
LOGGER.info(variable + "set to %s" % getattr(self, variable))
python 解释器提出
AttributeError: 'Example' object has no attribute 'self.csv'
(属性名称在 运行 时更改,因为字典未排序 - 属性本身并不重要)
重要的问题是,当我在 for 循环范围之外引用新变量时,可以访问它们而没有属性错误。他们的分配已经发生,他们是 class 的属性。这些变量在 dir(self) 和 self 中都可以找到。
这里 python 的什么特性阻止我访问 for 块(或 finally 块)内的这些变量?
编辑:
一个独立的例子:
class Example(object):
__vars_to_be_assigned: {"self.foo": "value", "self.bar": "not foo"}
def __init__(self):
for key, value in self.__vars_to_be_assigned:
try:
exec(key + " = value")
except:
print("Exception!")
else:
print(getattr(self, variable[5:]))
这个例子应该引发一个 AttributeError
这确实是 exec
的一个错误用法。做起来更简单:
class Example(object):
__tree_dict = {"genomedir": "genomes",
"pre_align": "pre_alignment",
"alignments": "alignments",
"trimmed": "trimmed",
"prf_pre": "prf_preprocess",
"scaled": "scaled",
"csv": "csv"}
def __init__(self, rootdir):
self._rootdir = Path(rootdir)
self.outdir = self.mksubdir(self._rootdir, "out")
for variable, human_readable in self.__tree_dict.items():
try:
setattr(self, variable, self.mksubdir(self.outdir,human_readable))
except:
LOGGER.error("%s failed to initialize as %s, defaulting output to root" (variable, human_readable), exc_info=True)
setattr(self, variable, Path(self._rootdir)
您收到错误的原因很简单,就是该属性被称为 csv
,而不是 self.csv
。使用 setattr
并从 __tree_dict
中的值中删除 self.
前缀将确保设置和获取值之间的一致性。
我知道大多数人不喜欢使用 exec 进行动态分配。但是,出于我的目的(务实和古怪),我想将变量名称视为数据。
考虑这个例子,我在 class 初始化期间使用它
现在我要给这些变量动态赋值
class Example(object):
__tree_dict = {"self.genomedir": "genomes",
"self.pre_align": "pre_alignment",
"self.alignments": "alignments",
"self.trimmed": "trimmed",
"self.prf_pre": "prf_preprocess",
"self.scaled": "scaled",
"self.csv": "csv"}
def __init__(self, rootdir):
self._rootdir = Path(rootdir)
self.outdir = self.mksubdir(self._rootdir, "out")
for variable, human_readable in self.__tree_dict.items():
try:
exec(variable + " = self.mksubdir(self.outdir,human_readable)")
except:
LOGGER.error("%s failed to initialize as %s, defaulting output to root" (variable, human_readable), exc_info=True)
exec(variable + '= Path(self._rootdir)')
这段代码会运行,但我不确定异常处理是否真的有效,因为当我添加一个 finally 语句将变量赋值写入记录器时,例如
finally:
LOGGER.info(variable + "set to %s" % getattr(self, variable))
python 解释器提出
AttributeError: 'Example' object has no attribute 'self.csv'
(属性名称在 运行 时更改,因为字典未排序 - 属性本身并不重要)
重要的问题是,当我在 for 循环范围之外引用新变量时,可以访问它们而没有属性错误。他们的分配已经发生,他们是 class 的属性。这些变量在 dir(self) 和 self 中都可以找到。
这里 python 的什么特性阻止我访问 for 块(或 finally 块)内的这些变量?
编辑:
一个独立的例子:
class Example(object):
__vars_to_be_assigned: {"self.foo": "value", "self.bar": "not foo"}
def __init__(self):
for key, value in self.__vars_to_be_assigned:
try:
exec(key + " = value")
except:
print("Exception!")
else:
print(getattr(self, variable[5:]))
这个例子应该引发一个 AttributeError
这确实是 exec
的一个错误用法。做起来更简单:
class Example(object):
__tree_dict = {"genomedir": "genomes",
"pre_align": "pre_alignment",
"alignments": "alignments",
"trimmed": "trimmed",
"prf_pre": "prf_preprocess",
"scaled": "scaled",
"csv": "csv"}
def __init__(self, rootdir):
self._rootdir = Path(rootdir)
self.outdir = self.mksubdir(self._rootdir, "out")
for variable, human_readable in self.__tree_dict.items():
try:
setattr(self, variable, self.mksubdir(self.outdir,human_readable))
except:
LOGGER.error("%s failed to initialize as %s, defaulting output to root" (variable, human_readable), exc_info=True)
setattr(self, variable, Path(self._rootdir)
您收到错误的原因很简单,就是该属性被称为 csv
,而不是 self.csv
。使用 setattr
并从 __tree_dict
中的值中删除 self.
前缀将确保设置和获取值之间的一致性。