2016-02-10 61 views
2

我有一個具有很長變量列表(至少一打)的類。在模塊中,我首先導入一個包含一些輔助方法和所有默認常量的常量文件。Python在初始化文件和默認常量文件中使用變量初始化類

from myConstants import * 

class SomeClass(ParentClass): 
    def __init__(var1=VAR1, ..., varN=VARN): 
     super(SomeClass, self).init(var1, ...) 
     self.varM = varM 

問題:我希望能夠指定一個文件時,我初始化該文件中包含的常量在myConstants.py一個子集類。不在init文件中的變量將從默認值加載。喜歡的東西:

sc = SomeClass(initFile='/path/to/file') 

我的想法是有東西像

from myConstants import * 
from ConfigParser import SafeConfigParser 

class SomeClass(ParentClass): 
    def __init__(var1=VAR1, ..., varN=VARN, initFile=''): 
     if initFile: 
      parser = SafeConfigParser().read(initFile) 
      var1 = parser('constants', 'var1') if parser('constants', 'var1') else VAR1 
      var2 = parser('constants', 'var2') if parser('constants', 'var2') else VAR2 
      .... 
      varN = parser('constants', 'varN') if parser('constants', 'varN') else VARN 
     else: 
      var1 = VAR1 
      ... 
      varN = VARN 

     super(SomeClass, self).init(var1, ...) 
     self.varM = varM 

問題:這是做到這一點的最好方法是什麼?如果不是,那是什麼?似乎有點囉嗦。我也沒有和ConfigParser結婚。

+2

提示:不要使用「通配符導入」,例如'from foo import *',要麼顯式地執行'from foo import bar1,bar2,bar3,...'或者'import foo'並執行'foo。 bar1,foo.bar2' – cowlicks

+0

我可以問爲什麼不呢?該文件包含很多變量/方法,大部分都在使用。顯式導入將會超長。加上任何時候添加新的常量,我將不得不進入並更改每個模塊文件。 – Sal

+1

所以你應該做第二個cowlicks的建議;只要做'import foo',然後將它們稱爲'foo.bar1'等等 - 當你添加新的時候不需要改變任何東西。 –

回答

2

我會使用兩個獨立的構造函數,一個需要一個文件,另一個需要顯式參數。

class SomeClass(ParentClass): 
    @classmethod 
    def from_file(cls, init_file): 
     parser = SafeConfigParser() 
     parser.read(init_file) 
     var1 = parser.get('constants', 'var1') if parser.has_option('constants', 'var1') else VAR1 
     # likewise var2, ..., varN 
     # This results in a call to cls.__init__ 
     return cls(var1, var2, ..., varN) 

    def __init__(var1=VAR1, ..., varN=VARN, initFile=''):    
     var1 = VAR1 
     ... 
     varN = VARN 

     super(SomeClass, self).init(var1, ...) 
     self.varM = varM 

x = SomeClass(1, 2, 3) 
y = SomeClass.from_file(config_file) 
0

人,這ConfigParser清楚地顯示出它的年齡 - 它definettely應該有一個映射接口 - 我不得不戳了一下 各地去一種方式來獲得它的價值觀 - 但這是一個更適合 代碼爲您提供:

class SomeClass(ParentClass): 
    options = {"var1": VAR1, "var2": VAR2, ...} 
    def __init__(initFile='', **kwargs): 
     options = self.__class__.options.copy() 
     if initFile: 
      parser = SafeConfigParser().read(initFile) 
      for option_name in parser.options("constants"): 
       if options_name in options: 
        options[option_name] = parser.get("constants", option_name) 
     else: 
      for key, value in kwargs: 
       if key in options: 
        options[key] = value 

     super(SomeClass, self).init(**options) 
     self.varM = varM 
0

你可以嘗試使用configparser對象,並對其進行修改以滿足您的需求使用默認值的字典:

default_values = { 
    "var1": "42", 
    "var2": "23", 
} 

conf_parser = configparser.ConfigParser() 
conf_parser.read(config_file) 

for var, default_value in default_values.keys(): 
    if v not in conf_parser["DEFAULT"]: 
     conf_parser["DEFAULT"][var] = default_value 

這應該覆蓋configparser中的所有缺失值。 之後,您可以傳遞configparser對象並使用config_parser["DEFAULT"]["var1"]等訪問所有變量。這有好處,你所有的變量都整齊地捆綁在一起,你只有一個構造函數的參數。

另一方面,這有點難看,配置解析器只知道如何使用字符串,所以也許字典會更適合這個任務。

我希望這會有所幫助。