global关键字怎么在python中使用
这期内容当中小编将会给大家带来有关global关键字怎么在python中使用,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
摘要
global标志实际上是为了提示 python 解释器,表明被其修饰的变量是全局变量。这样解释器就可以从当前空间 (current scope) 中读写相应变量了。
Python 的全局变量是模块 (module) 级别的
每个 python 函数拥有对应的__globals__字典,该字典与函数所属模块的__dict__字典完全相同。函数的全局变量也会从这个字典中获取
注:上面三句话的意思就是,python 解释器发现函数中的某个变量被global关键字修饰,就去函数的__globals__字典变量中寻找(因为 python 中函数也是一等对象);同时,一个模块中每个函数的__globals__字典变量都是模块__dict__字典变量的引用,二者值完全相同。
避免全局变量将使得程序更容易被调试,同时也能提升程序的可读性
使用到的全局变量只是作为引用,不在函数中修改它的值的话,不需要加global关键字.使用到的全局变量,需要在函数中修改的话,就涉及到歧义问题. 因此在函数中修改全局变量的话需要加global关键字
动机
我最近遇到了一个关于 python 全局变量的问题,如下面这个简单例子里展示(当然实际代码要比这个复杂的多,这里只是一个抽象出来当例子)。例子中foo.py定义了函数f,而函数f调用了全局变量a:
#foo.py deff(): print(a) defmain(): globala a=5 f() if__name__=='__main__': main()
运行上面这个文件将如预料中的输出5。在另一个文件bar.py中我们引入上面的f,代码如下
#bar.py fromfooimportf defmain(): f() main()
运行bar.py将报NameError错误。这是因为a被定义在foo.py的main函数中,而当导入f函数时,foo.py的main函数并未被运行,所以a也没哟被定义。
Traceback(mostrecentcalllast): File"bar.py",line10,in<module> main() File"bar.py",line7,inmain f() File"foo.py",line5,inf print(a) NameError:globalname'a'isnotdefined
定义全局变量a
为了修复上面当问题第一反应是在bar.py中定义全局变量a,这样f就可以找到变量a了,如下面的代码:
#bar.py fromfooimportf defmain(): globala a=4 f() main()
然而依旧会报错,黑人问号脸???
Traceback(mostrecentcalllast): File"/tmp/example/bar.py",line13,in<module> main() File"/tmp/example/bar.py",line9,inmain f() File"/tmp/example/foo.py",line5,inf print(a) NameError:globalname'a'isnotdefined
函数的__globals__属性与 python 的global语句
python 的global语句的作用只是提示 python 解释器,被global修饰的变量是一个全局变量,利用上面例子里函数f的反编译代码可以清除的看到这一点:
importdis fromfooimportf dis.dis(f)
50LOAD_GLOBAL0(print) 2LOAD_GLOBAL1(a) 4CALL_FUNCTION1 6POP_TOP 8LOAD_CONST0(None) 10RETURN_VALUE
面可以看出变量a被认为是全局变量。Python 中的每一个函数都拥有一个__globals__字典变量,该变量实际是函数所属模块的__dict__变量的引用。所以在bar.py中我们想在bar.main函数中将全局变量a赋值为4,实际改变的是bar.py的__dict__字典变量 (注:而不是定义f的foo.py的__dict__字典变量)
#bar.py defmain(): globala a=4 print(main.__globals__.keys()) print(main.__globals__['a']) dict_keys(['__name__','__doc__','__package__','__loader__','__spec__','__annotations__','__builtins__','__file__','__cached__','foo','f','dis','main','a']) 4
上面的代码输出了main.__globals__(即bar.__dict__) 中全局变量a的值是4,然而这个值对函数f来说确是不可见的,因为f.__globals__实际等于foo.__dict__(简单而言就是命名空间不同)
fromfooimportf print(f.__globals__)
假设我们在foo.py所有函数的外部预先定义了全局变量a,那么在将函数f导入时,a会随着f.__globals__一同被导入。但这时被导入的f.__globals__["a"]( 即foo.__dict__["a"]) 和bar.main中赋值的bar.main.__globals__["a"]( 即bar.__dict__["a"]) 仍然不是同一个变量,即赋值无法改变函数f的输出,如下面的例子所示。
#foo.py a=3 deff(): print(a) defmain(): globala a=5 f() if__name__=='__main__': main()
#bar.py fromfooimportf defmain(): globala a=4 f() main()
运行bar.py输出3,而不是 4。
修改函数全局变量的值:更新globals
就上述例子而言,如果我们想在bar.py中改变函数f的输出,则需要直接更新其__globals__变量的值。
#bar.py fromfooimportf defmain(): f.__globals__['a']=4 f() main()
模块的dict变量和猴子布丁 (monkey-patching)
如上所述,函数的__globals__变量实际是其所属模块__dict__变量的引用。所以为了达到上面修改全局变量的目的,也可以直接更新foo.__dict__。修改模块foo的属性 (attribute) 值即可直接更新foo.__dict__。
#bar.py importfoo fromfooimportf defmain(): foo.a=4 f()
如果你曾经使用过运行中给代码打补丁的库,一般就是这么实现的。直接修改被打补丁的模块的__dict__中特定的对象或函数。、
输入使得函数变得更加容易测试上面的例子中的函数f如果接受输入变量的话,而不是使用全局变量,代码将更容易被测试。同时可读性也更好,出了问题也更容易 debug。
#foo.py deff(a): print(a) defmain(): a=5 f(a) if__name__=='__main__': main()
#bar.py fromfooimportf defmain(): a=3 f(a)
上述就是小编为大家分享的global关键字怎么在python中使用了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注恰卡编程网行业资讯频道。
推荐阅读
-
Python中怎么动态声明变量赋值
这篇文章将为大家详细讲解有关Python中怎么动态声明变量赋值,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文...
-
python中变量的存储原理是什么
-
Python中怎么引用传递变量赋值
这篇文章将为大家详细讲解有关Python中怎么引用传递变量赋值,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文...
-
python中怎么获取程序执行文件路径
python中怎么获取程序执行文件路径,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的...
-
Python中如何获取文件系统的使用率
Python中如何获取文件系统的使用率,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴...
-
Python中怎么获取文件的创建和修改时间
这篇文章将为大家详细讲解有关Python中怎么获取文件的创建和修改时间,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读...
-
python中怎么获取依赖包
今天就跟大家聊聊有关python中怎么获取依赖包,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据...
-
python怎么实现批量文件加密功能
-
python中怎么实现threading线程同步
小编给大家分享一下python中怎么实现threading线程同步,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!...
-
python下thread模块创建线程的方法
本篇内容介绍了“python下thread模块创建线程的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来...