python中global變量釋疑

疑問

  1. 爲何main中不能寫global x語句?
  2. 在函數中如何修改global變量?
  3. 在main中修改了global變量後,在子進程中爲何沒有效果?
  4. 如何利用進程池的initializer參數(函數)修改子進程中的global變量?

代碼以下:python

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 # @Time : 2018/9/1 8:21
 4 # @Author : dswang
 5 
 6 from multiprocessing import Pool, current_process  7 
 8 VAR0 = 'module'
 9 
10 
11 def f0(change=False): 12     print 'in func f0, pid:{}'.format(current_process().pid) 13     # time.sleep(2)
14     if change: 15         global VAR0 16         VAR0 = 'f0'
17     print VAR0 18 
19 
20 def ps_init(): 21     global_dct = globals() 22     print "global_dct.keys():", global_dct.keys() 23     print 'VAR0 in global:', global_dct.get('VAR0') 24     global VAR0 25     VAR0 = 'ps'
26     print 'VAR0 in global:', global_dct.get('VAR0') 27 
28 
29 if __name__ == '__main__': 30     VAR0 = 'main'
31     pool = Pool(processes=1, initializer=ps_init) 32     pool.apply(func=f0, args=()) 33 
34  f0() 35  f0(True) 36     print 'in main, pid:{}'.format(current_process().pid) 37     print 'VAR0 in main:'
38     print VAR0 39 
40     print 'the end'

結果爲:app

 1 global_dct.keys(): ['f0', 'VAR0', '__builtins__', '__file__', '__package__', 'current_process', '__name__', '__doc__', 'Pool', 'ps_init']  2 VAR0 in global: module  3 VAR0 in global: ps
 4 in func f0, pid:6504
 5 ps
 6 in func f0, pid:6216
 7 main  8 in func f0, pid:6216
 9 f0 10 in main, pid:6216
11 VAR0 in main: 12 f0 13 the end

 

解疑

一、爲何main中不能寫global x語句?函數

由於 if __name__ == '__main__': 語句並不開闢新的做用域,因此main中的變量VAR0已是在全局做用域,ui

再寫關鍵字global是多餘的,會報錯:spa

SyntaxWarning: name 'VAR0' is assigned to before global declaration global VAR0.

 

二、在函數中如何修改global變量?code

在函數中修改global變量,須要先聲明變量爲global,如代碼1624行中,在函數f0中的「global VAR0」語句。orm

 

三、在main中修改了global變量後,在子進程中爲何沒有效果?blog

注:6216是主進程,6504是子進程。進程

從運行結果中看到(結果第2行):子進程中的VAR0並無由於main中的修改而改變,ip

依然保持module中的值「module」。當子進程中修改後,VAR0變成了「ps」,在隨後f0函數中依然是"ps"。

而後,回到main中(代碼34行),VAR0爲main中修改後的「main」。最後,main中函數f0對VAR0再次修改成「f0」,

所以,VAR0在f0和main中都變成了「f0」,見結果第9和第12行。

 

四、如何利用進程池的initializer參數(函數)修改子進程中的global變量?

參考代碼和問題3的回答。

 

總結

  1. if語句不開闢新的做用域,所以不能在main中寫global關鍵字,直接修改便可;
  2. 函數中要修改全局變量,須要先聲明爲全局變量:global x;
  3. 子進程中的全局變量取module中的值,main中修改module的全局變量不影響子進程
相關文章
相關標籤/搜索