模块变量和全局变量有什么区别?

11

来自一条评论:“Python中的global基本上是指在模块级别”。然而,在名为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()的一部分?

1个回答

9

Python中基本上有3种不同的范围:

  • 模块范围(将属性保存在模块的__dict__中)
  • 类/实例范围(将属性保存在类或实例的__dict__中)
  • 函数范围

它们几乎相同,除了类作用域可以动态地使用__getattr__或__getattribute__来模拟不存在的变量。而函数则不同,因为您可以将变量传递给函数(使其成为其范围的一部分)并从函数中返回。

但是,当您谈论全局(和本地)范围时,您必须考虑其可见性。没有“总体全局范围”(除了像int,zip等Python内置对象),只有“全局模块范围”。这代表您可以在模块中访问的所有内容。

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

enter image description here

然后你使用 import my_module as m ,这意味着 m 现在是指向 my_module 的引用,并且该引用位于当前文件的全局作用域中。这意味着 'm' in globals() 将会返回 True。

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。这不会使mfoobar成为当前全局范围的一部分。它们仍然在my_module的全局范围内,但是您可以通过全局变量m访问my_module的全局范围。

enter image description here

我在这里使用了AB来缩写模块名称,但我希望它仍然可以被理解。

非常清楚,我的错误在于没有理解两个foo是不同的实体,否则我也会质疑其他的。顺便说一下,我现在也明白了我可以访问m.m.m.m.bar - mins
我有一个问题:导入模块本身是否有实际用途?还是只是出于好奇? - MSeifert
这不是一个真实的案例。只是想比较__dict__globals()的内容。我无法在不导入的情况下进行比较。 - mins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接