2017-09-03 134 views
3

a comment:“全球在Python中基本上意味着在模块级别”。然而,在一个名为my_module.py文件运行此代码:什么是模块变量与全局变量?

import my_module as m 

foo = 1 
m.bar = m.foo + 1 

if __name__ == "__main__": 
    print('foo:', foo) 
    print('m.foo:', m.foo) 
    print('m.bar:', m.bar, '\n') 

    for attrib in ('foo', 'bar'): 
     print("'{0}' in m.__dict__: {1}, '{0}' in globals(): {2}".format(
      attrib, 
      attrib in m.__dict__, 
      attrib in globals())) 

输出:

foo: 1 
m.foo: 1 
m.bar: 2 

'foo' in m.__dict__: True, 'foo' in globals(): True 
'bar' in m.__dict__: True, 'bar' in globals(): False 

究竟是模块和全局命名空间?

为什么在模块命名空间中有__dict__属性,但不在全局命名空间中?

为什么m.bar部分__dict__而不是globals()的一部分?

回答

3

基本上有3个不同的的范围在Python:

  • 模块范围
  • 类/实例范围(保存在类或实例__dict__属性)(在模块__dict__保存属性)
  • 功能范围

(也许我忘了的东西有...)

这些工作几乎相同,除了类作用域可以动态使用__getattr____getattribute__来模拟实际上不存在的变量的存在。而函数是不同的,因为你可以传递变量(使它们成为其作用域的一部分)并从函数中返回它们。

然而,当你谈论全球(和本地范围)时,你必须从可见性的角度来考虑它。全球范围内没有(除了Pythons内置插件,例如intzip等),只有全局模块范围。这代表您可以在模块中访问的所有内容。

因此,在你的文件的开头这个“大致”表示模块范围:

enter image description here

然后你import my_module as m这意味着m现在是my_module参考,该基准是在全球范围内的当前文件。这意味着'm' in globals()将为真。

enter image description here

也可以定义foo=1,使您的全球范围的foo一部分,'foo' in globals()True。但是foom.foo完全不同!

enter image description here

那么你就m.bar = m.foo + 1访问全局变量m并且基于m小号属性foo属性bar。这不会使m s foobar成为当前全球范围的一部分。它们仍位于my_module的全球范围内,但您可以通过全局变量m访问my_module的全局范围。

enter image description here

AB这里缩写模块名称,但我希望它仍然是可以理解的。

+0

很清楚,我的错误并不是要明白两个foo是不同的实体,否则我也会挑战其余的。顺便说一句,我现在也明白我也可以访问'm.m.m.m.bar': – mins

+0

我有一个问题,但是:是否有一个实际的用例来导入模块本身?还是只是好奇? – MSeifert

+0

不是一个真实的案例。试图比较'__dict__'和'globals()'的内容。我不能没有进口。 – mins

-1

全局变量是您可以在任何给定时间使用变量的地方,即使在函数或for循环中也是如此。局部变量在函数中定义,但不返回。