exec(变量=)在for循环中分配的变量范围?

时间:2017-02-21 19:50:34

标签: python object error-handling scope variable-assignment

我知道大多数人不喜欢使用exec进行动态分配。但是,我想将变量名称视为我的目的(实用和偏心)。

考虑这个例子,我在类初始化期间使用

现在我要动态分配这些变量

 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循环范围之外的新变量时,它们是可访问的,没有属性错误。他们的任务已经完成,他们是班级的属性。这些变量既可以在dir(self)中找到,也可以在self中找到。

python的哪些功能在这里阻止我访问for block(或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

1 个答案:

答案 0 :(得分:3)

这对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并从self.中的值中删除__tree_dict前缀将确保设置和获取值之间的一致性。

相关问题