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

昨天在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对象

### 回答1: 这种情况通常是因为在模块中没有定义全局变量,或者在使用全局变量之前没有正确地初始化它们。要解决这个问题,可以在模块中定义全局变量,并确保在使用它们之前正确地初始化它们。另外,也可以使用global关键字来在函数内部引用全局变量。 ### 回答2: Python是一种可编程的高级脚本语言,在python的编程过程中,变量是程序中重要的组成部分。Python中的变量分为两种类型,全局变量和局部变量。 在Python中,全局变量是指在程序的任意位置都可以访问的变量,而不是局限于任何一个函数或类。通常在模块的顶部定义一个全局变量,它可以在模块中的任何地方使用。 但是,在默认情况下Python全局变量模块级别未定义。也就是说,如果在模块中定义一个变量,它将只在模块的函数中可用,而不能在模块的其它位置或函数之外使用。 Python全局变量仅在该模块的命名空间内定义,在函数内部定义的变量的生命周期仅在该函数内,不能在该函数之外使用。 如果想要在Python中使用全局变量,需要在该模块中显式地声明全局变量。声明语法为:global 变量名称。 例如: x = 5 def func(): global x x = x + 1 print(x) func() 在上面的代码中,我们定义了一个全局变量x,并在函数中使用global x声明,以便可以在函数中使用该全局变量。最后输出的x结果为6。 总之,在Python编程中,全局变量需要进行特殊声明,才能在函数和模块的任意位置使用,否则它只能在模块的函数内使用。 ### 回答3: 在Python中,全局变量是在模块级别定义的变量。这意味着,当在一个模块中声明一个变量时,该变量的作用域是整个模块,而不是在模块以外的任何地方。换句话说,定义全局变量时需在模块层级进行。 如果在函数中定义变量,那么变量的作用域只在该函数内部,如果要在函数外部访问该变量,则需要将其声明为全局变量,否则在函数外部无法使用它。 需要注意的是,如果在一个模块的函数中,在函数内声明一个全局变量,那么它在函数外部是不可访问的。这是因为变量作用域仅限于内部函数而不是整个模块。 在模块内,要访问全局变量,只需直接使用变量名即可。如果要从模块外部访问全局变量,则需要使用 "module_name.variable_name"语法来访问全局变量。 由于Python全局变量的作用域是整个模块,因此在编写程序时需要注意全局变量的使用。全局变量的滥用会导致程序变得难以理解和维护。因此,需要仔细考虑何时使用全局变量,以及需要在哪里进行定义。 总之,Python全局变量模块级别定义,需要在模块层级进行定义,才能在整个模块中访问和使用。同时,需要注意全局变量的使用方法和场合,以避免程序出现错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值