Python中import外部模块全局变量修改规则及踩坑

Python中import外部模块全局变量修改规则及踩坑,第1张

概述最近碰到一个import外部文件全局变量修改后未符合预期效果的问题,简要描述如下: 有env.py, test.py, dal.py三个文件,env.py 中定义了DEBUG=False的全局变量,d

最近碰到一个import外部文件全局变量修改后未符合预期效果的问题,简要描述如下:

有env.py,test.py,dal.py三个文件,env.py 中定义了DEBUG=False的全局变量,dal.py中部分代码会根据DEBUG取值决定是否走调试逻辑,在test.py中通过from env import DEBUG后,设置DEBUG=True,然而在dal.py中实际使用DEBUG时却发现DEBUG取值依然是False,并没有修改成功。简化代码如下:

# env.pyDEBUG = False
 dal.pyfrom env import DEBUGdef test():    if DEBUG:        print('DEBUG logic')    else:        online logic')

 test.py dalif __name__ == __main__:    DEBUG = True    dal.test()

执行结果:

$ python test.pyonline logic

一时之间觉得非常奇怪,探究了一下其具体原因,发现实际要想修改import的其他模块全局变量取值并生效,还真有些讲究在里面,这里总结分享一下。

全局变量的修改对于值类型和引用类型规则并不相同,因而以下举例中同时定义了gx/gy作为值类型代表,gdctx/gdcty作为引用类型代表,同时为了跟踪是否指向同一对象,使用ID函数打印出了每一变量的对象ID。

定义以下下代码文件:

 env.pygx = envgy = gdctx = {': }gdcty = {}gx:{}|{}\tgy:{}|{}\tgdctx:{}|{}\tgdcty:{}|{}\tin env'.format(ID(gx),gx,ID(gy),gy,ID(gdctx),gdctx,ID(gdcty),gdcty))
 mods.py gx,gdcty env print_env():    gx:{}|{}\tgy:{}|{}\tgdctx:{}|{}\tgdcty:{}|{}\tin mods.format(ID(gx),gdcty))    gx:{}|{}\tgy:{}|{}\tgdctx:{}|{}\tgdcty:{}|{}\tin mods.env'.format(ID(env.gx),env.gx,ID(env.gy),env.gy,ID(env.gdctx),env.gdctx,ID(env.gdcty),env.gdcty))

test1.py中通过import env中的全局变量直接进行修改:

 test1.py envfrom mods  print_envgx = test1'  实际生成了新的值对象,对象ID发生变动gdctx['] =  对引用类型dict修改了k/v,对象ID不变 test():    gy = ' # 未添加global声明,实际生成了新的局部变量gy,不影响全局变量    gdcty = {} # 未添加global声明,实际生成了新的局部变量gdcty,不影响全局变量:    gx:{}|{}\tgy:{}|{}\tgdctx:{}|{}\tgdcty:{}|{}\tin test1gx:{}|{}\tgy:{}|{}\tgdctx:{}|{}\tgdcty:{}|{}\tin test1.env.format(ID(env.gx),env.gdcty))    print_env()

执行 test1.py:

$ python test1.pygx:4508684848|env    gy:env    gdctx:4509665632|{'}      gdcty:4509713664|{'}    in env  # env.py中的对象ID及取值gx:4510060784|test1  gy:'}    gdcty:in test1 # test1.py中gx已经是不同的对象ID与取值,gdctx内容发生变化,但依然指向同一对象,gy、gdcty不受影响gx:in test1.env # 通过env.* 形式直接引用env中的变量,对象ID不变,gdctx内容发生变化 mods # 保持指向最开始import时的env.*对象,注意gx不受test1.py中的修改影响gx:in mods.env # env.*形式引用env.py中的相同变量,对象ID不变,gdctx内容发生变化

 

test2.py中通过env.*、global声明的形式修改全局变量取值:

 test2.py print_envenv.gx = test2' # 通过env.gx引用值类型,相当于将env.gx指向新生成的值对象,env.gx对象ID发生变化env.gdctx = {} # 通过env.gdctx引用引用类型,将其指向一个新的dict对象,env.gdctx对象ID发生变化global gy,gdcty    gy = ' # 添加global声明后指向全局变量gy,将其指向新对象,gy对象ID发生变化 {} # 指向新的dict对象,gdcty ID发生变化:    test()    gx:{}|{}\tgy:{}|{}\tgdctx:{}|{}\tgdcty:{}|{}\tin test2gx:{}|{}\tgy:{}|{}\tgdctx:{}|{}\tgdcty:{}|{}\tin test2.env4502704816|4503685552|{'}        gdcty:4503733584|{env4504080752|test2  gdctx:4502670384|{}     test2 # gx、gdctx保持import时的原值不受赢下,gy指向新值对象,gdcty指向新的dict对象gx:4504080752|test2  gy:4502670144|{in test2.env # env.gx、env.gdctx指向新的对象,env.gy、env.gdcy不受影响 mods # 保持指向最开始import时的env.*对象,无任何变动gx:env # env.gx、env.gdctx已经指向新的对象,env.gy、env.gdcty不变

通过test1.py、test2.py的执行结果可以得出以下结论:

1,from XX import YY的方式导入全局变量后,如果XX.YY取值在某一模块发生了修改导致其指向的对象发生了变化(对象ID不同),其他模块引入的YY并不会同步修改,而是指向最初的取值。因而考虑全局变量修改的情况下,应使用import XX,而后使用XX.YY的方式进行引用。

2,值类型赋不同值肯定会导致对象ID变化,因而无法跨文件传递修改内容,引用类型如果整体被指向新对象会导致对象ID变化,同样无法跨文件传递修改,但是只修改引用对象本身的某部分内容则不会生成新对象,修改可以成功跨文件传递。

3,函数中引用全局变量,如果只是读取,会先查找同名本地变量,而后全局变量,但是如果涉及赋值、修改其语义则是定义一个新的局部变量,此时要记住使用global声明对应的全局变量。

 

转载请注明出处,原文地址:https://www.cnblogs.com/AcAc-t/p/python_global_import_rule.html

总结

以上是内存溢出为你收集整理的Python中import外部模块全局变量修改规则及踩坑全部内容,希望文章能够帮你解决Python中import外部模块全局变量修改规则及踩坑所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1157854.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-01
下一篇 2022-06-01

发表评论

登录后才能评论

评论列表(0条)

保存