2017-02-21 104 views
0

我知道大多数人不是使用exec来做动态分配的粉丝。不过,我想将变量名称作为数据用于我的目的(既实用又古怪)。在for循环中由exec(variable =)赋值的变量范围?

考虑这个例子,我一类的初始化过程中正在使用

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

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: 
      LOGGER.info(variable + "set to %s" % getattr(self, variable)) 

python解释器r aises

AttributeError: 'Example' object has no attribute 'self.csv' 

(属性名称在运行时改变,因为字典里没有下令 - 属性本身并不重要)

重要的问题是,当我引用的范围之外的新变量for循环,它们可以访问w/no属性错误。他们的任务已经发生,他们是班级的属性。这些变量都可以在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

+0

你能提供一个最小的自包含的例子吗?另外,Python版本会影响到这一点,因为'exec'的语义从Python 2更改为3. –

+0

您是否在Python 3上?可能,这个问题将是照亮:http://stackoverflow.com/questions/15086040/behavior-of-exec-function-in-python-2-and-python-3 –

+0

原来是一个简单的语法错误属性引用(自我没有属性self.self.attribute)。不过,谢谢这个链接对未来的探索有帮助 –

回答

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

+0

谢谢!接得好。简单的错误。另外,我没有考虑使用setattr。谢谢 –