您的位置:首页 > 编程语言 > Python开发

Python全局变量在模块之间引用的问题

2013-10-10 11:42 579 查看
昨天在Python群里有人提到一个问题,在模块a中引入模块b的全局变量x,并在a中调用b的函数来修改x的值,结果出现很难理解的现象。经过反思发现自己对这个概念也是一知半解,好像在《Python源码剖析》那本书中看到过相关的知识但是又有些记不太清,故编写程序做一些验证以扫清编码障碍,至于实现层面的理解等晚一点再翻翻书(PS: 这件事情显示读书笔记还是很重要的,不然每次都得去书中重新找相关信息)。

这其实是两个问题:1.from moduleA import * 和import moduleA在使用全局变量上的区别; 2.__main__模块横插一脚会怎样?

1.程序

[dongsong@localhost python_study]$ cat testc.py
import pprint, sys, pdb
a = list()
b = list()
def A():
global a
a = dict()
b.append(100)
print "A() a = %r, b = %r" % (a,b)
[dongsong@localhost python_study]$ cat testd.py
#encoding=utf8
import pprint, sys, pdb

if __name__ == "__main__":
if len(sys.argv) == 1:
print "Usage:\n\tpython %s 1/2" % __file__
sys.exit()

if int(sys.argv[1]) == 1:
print "import testc ..."
import testc
print "testc.a = %r, testc.b = %r" % (testc.a, testc.b)
testc.A()
print "testc.a = %r, testc.b = %r" % (testc.a, testc.b)

elif int(sys.argv[1]) == 2:
print "from testc import *"
print "before import: globals().keys() = %r" % globals().keys()
from testc import *
print "after import: globals().keys() = %r" % globals().keys() #可以看到testc模块中的符号都被导入__main__模块的全局名字空间里了
print "a = %r, b = %r, sys.modules['testc'].a = %r, sys.modules['testc'].b = %r" % (a, b, sys.modules['testc'].a, sys.modules['testc'].b)
A() #WARNING:A()函数让testc模块中的符号a指向了新的对象,故testc和__main__中的"a"符号指向了不同对象;A()函数没有改变"b"符号指向的对象,只是修改了该对象的元素,故testc和__main__中的"b"符号对应的数值都跟着变化(还是指向同一个对象)
print "a = %r, b = %r, sys.modules['testc'].a = %r, sys.modules['testc'].b = %r" % (a, b, sys.modules['testc'].a, sys.modules['testc'].b)

else:
print "error argv.."

结果

[dongsong@localhost python_study]$ vpython testd.py 1
import testc ...
testc.a = [], testc.b = []
A() a = {}, b = [100]
testc.a = {}, testc.b = [100]
[dongsong@localhost python_study]$ vpython testd.py 2
from testc import *
before import: globals().keys() = ['__builtins__', '__file__', 'pprint', '__package__', 'sys', 'pdb', '__name__', '__doc__']
after import: globals().keys() = ['a', 'A', 'b', '__builtins__', '__file__', 'pprint', '__package__', 'sys', 'pdb', '__name__', '__doc__']
a = [], b = [], sys.modules['testc'].a = [], sys.modules['testc'].b = []
A() a = {}, b = [100]
a = [], b = [100], sys.modules['testc'].a = {}, sys.modules['testc'].b = [100]

一目了然,不做赘述!

2.程序

[dongsong@localhost python_study]$ cat testa.py
import pprint, sys, pdb
a = list()
b = list()
def A():
global a
a = dict()
b.append(100)
print "A() a = %r, b = %r" % (a,b)

if __name__ == '__main__':
import testa
testaInModules = sys.modules['testa']
testaAsMain = sys.modules['__main__']
print "testa: id = %r, file = %r" % (id(testa), testa.__file__)
print "testaInModules: id = %r, file = %r" % (id(testaInModules), testaInModules.__file__)
print "testaAsMain: id = %r, file = %r" % (id(testaAsMain), testaAsMain.__file__)
print ""

A()

print ""
print "testa: a = %r, b = %r" % (testa.a,testa.b)
print "testaInModules: a = %r, b = %r" % (testaInModules.a,testaInModules.b)
print "testaAsMain: a = %r, b = %r" % (testaAsMain.a,testaAsMain.b)
print ""

#import testb
#testb.B()

结果

[dongsong@localhost python_study]$ vpython testa.py
testa: id = 140681127912120, file = '/home/dongsong/python_study/testa.py'
testaInModules: id = 140681127912120, file = '/home/dongsong/python_study/testa.py'
testaAsMain: id = 140681230481008, file = 'testa.py'

A() a = {}, b = [100]

testa: a = [], b = []
testaInModules: a = [], b = []
testaAsMain: a = {}, b = [100]


把testa模块作为__main__模块时,在内存中__main__模块跟testa模块虽然是由相同的源码(相同的字节码文件testa.pyc)加载的,但是它们是两个独立的module对象
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: