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的全局变量不影响子进程
相关文章
相关标签/搜索