重新考虑重复全局字典初始化

时间:2014-03-21 02:06:03

标签: python python-2.7 refactoring

我目前有一个全局词典变量

_vars ={
   "key_1":"system environmental variable_1",
   "key_2":"system environmental variable_2",
   ................
   #around eight key pairs
}

当程序通过调用initalize_vars函数运行时,字典_vars将被初始化

def initialize_vars():
    var key in _vars:
        _vars[key] = os.path.expandvars(vars[key])

但是,在基于用户提供的参数数量的主函数中,将调用不同的函数,其中一些函数不需要初始化_vars(它将引发异常,因为系统环境变量不存在)

例如:

def A():
    initialize_vars()
    #do something
    return something

def B():
   #do something
   return something

def C():
   initialize_vars()
   #do something

def main(): if sys.argv[1]=="A": A() elif sys.argv[1] =="B": B() elif sys.argv[1] =="C": C()

所以我的问题是:如果initialize_vars()已经初始化,则确保initialize_vars()多次调用的最佳方法是什么

2 个答案:

答案 0 :(得分:1)

我认为你可以添加一个全局变量来存储字典的初始化状态,当调用方法 initialize_vars 时,你可以通过检查这个全局变量的值来决定是否需要初始化。

示例代码如下

vars_initialized = False
def initialize_vars():
    global vars_initialized
    if False == vars_initialized:
        var key in _vars:
            _vars[key] = os.path.expandvars(vars[key])
        vars_initialized = True
  • 注意:但是当您读取/更新此全局变量的值时请注意锁定和线程安全,以下是可能发生的情况:

    1. 代码执行运行方法initialize_vars并尝试初始化var并进行处理。
    2. 代码执行B遇到方法initialize_vars并且 vars_initialized 的值为False,也尝试初始化它。
    3. 代码执行A完成初始化并将vars_initialized设置为True。
    4. 代码执行B完成初始化并将vars_initialized设置为True。

所以你可以看到,上面的代码执行过程是不正确的,正确的是

  1. 代码执行运行方法initialize_vars并尝试初始化var并进行处理。
  2. 代码执行B遇到方法initialize_vars并发现它已经被初始化,所以它会等到那个过程结束。
  3. 代码执行A完成初始化并将vars_initialized设置为True。
  4. 代码执行B获得vars_initialized为True的状态并继续执行。
  5. 所以这里是代码的另一个版本可能更好:

    vars_initialized = False
    vars_initialing  = False
    def initialize_vars():
        global vars_initialized, vars_initialing
        vars_initialing = True
        if False == vars_initialized:
            var key in _vars:
                _vars[key] = os.path.expandvars(vars[key])
            vars_initialized = True
        vars_initialing = False
    
    def A():
        if not vars_initialing:
            initialize_vars()
        else:
           while vars_initialing:
             //Wait for the init to be finished
              sleep(0.1) 
        #do something
        return something
    
    def B():
       #do something
       return something
    
    def C():
        if not vars_initialing:
            initialize_vars()
        else:
           while vars_initialing:
             //Wait for the init to be finished
              sleep(0.1) 
        #do something
        return something
    
    def main():
        if sys.argv[1]=="A":
           A()
        elif sys.argv[1] =="B":
           B()
        elif sys.argv[1] =="C":
           C()
    

    我熟悉Java并且在这种情况下我们使用Object locker(synchronized),我认为Python需要一些平等来确保这里没有发生冲突,我上面发布的只是一个模拟这个储物柜。

    这里可能会使用一些称为线程锁的东西,这里有一些引用。

答案 1 :(得分:1)

"最佳&#34 ;?值得商榷。可能是最简单的:

initialized=False
def A():
    initialize_vars()
    #do something
    return something

def B():
   #do something
   return something

def C():
   initialize_vars()
   #do something

def initialize_vars():
   if not initialized:
      initialized = True
      for key in _vars:
         _vars[key] = os.path.expandvars(vars[key])

如果您需要(我怀疑您可能),您可以在布尔词典中跟踪每个变量的初始化状态。这样,只有尚未初始化的变量才会在initialize_vars函数中初始化