2017-02-21 120 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。謝謝 –