【问题标题】:Concept of namespace, global, local with respect to import命名空间的概念,全局的,关于导入的局部的
【发布时间】:2020-01-04 00:54:15
【问题描述】:

我了解以下是 python 中的范围级别(按从高到低的顺序列出)

  • Lo​​cal(L):在函数/类内部定义
  • Enclosed(E):定义在封闭函数内部(嵌套函数概念)
  • Global(G):定义在最上层
  • 内置 (B):Python 内置模块中的保留名称

当我们只有一个文件时,我理解这个概念。我试图了解在 python 中使用import 时,命名空间、本地、封闭、全局、内置的这个概念是如何工作的。

我知道我们可以使用 foll 导入。方法:

  1. 导入模块名
  2. 导入模块名.function(函数/变量)
  3. 导入 package.module.function(函数/变量)
  4. 从模块导入函数(函数/变量)
  5. 从包导入模块
  6. 从 package.module 导入函数(函数/变量)
  7. 从模块导入 *
  8. 从包导入 *

我知道在上面的每一个中,整个模块都加载到 sys 模块字典中。但我对命名空间、范围、全局、本地感到困惑。我想了解 LEGB 原理、命名空间、全局、本地关于导入与从导入的方法。我已经读过,在第 1 点 (import modulename) 的情况下,模块名被加载到它自己的命名空间中,并且调用模块可以使用引用来全局更改变量值。这是否也意味着它在全局命名空间中?如果是这样的话,那么全球性的呢?我还读到from module import function/variablefrom module import * 在调用模块命名空间中带来函数/变量,并且任何更改都不是全局的。这是否意味着它在本地命名空间中?本地相对于什么?

示例: 假设模块 foo 有一个变量 bar=10。当我们使用 [import foo] - 这会将 foo 带入当前命名空间并允许我们通过 foo.bar=1000 更改 bar 的值,并且此更改对使用 [import foo print(foo. bar)] 完成上述任务后。在 [from foo import bar] 的情况下,对 bar 所做的任何更改仅对该模块可见,而对任何其他模块均不可见,无论它们是执行 [import foo] 还是 [from foo import bar],它们都会看到值小节为 10。

这方面的任何参考/链接都将非常有帮助。我想了解它在内部是如何工作的基础知识。任何信息都将有助于理解这一点。我在这个主题上找到的文章解释了什么是 import vs from xx import yy。但他们没有解释为什么/如何所做的更改成为全局(在导入的情况下)与本地(在从导入的情况下)。

更多示例: 在下面的代码示例中,对 a 的更改仅在 main.py 文件中可见,不会影响 module1.py 中 a 的值,并且导入 module1.py 的后续模块仍会看到 a 的值为 10。

module1.py:

a=10 main.py:

从模块 1 导入一个 打印(一) a=100 而如果我们使用 import module1 而不是 from module1 import a 那么分配将更改 module1.py 中 a 的值,并且任何后续 import module1.py 都会将 a 的值显示为 100。

注意:类似地,我们也可以在 module.py 中使用函数来获取和设置变量“a”的值。使用这种方法,一旦我们在 main.py 中执行 'from module1 import getfn, setfn',我们就可以使用这些函数,在调用时对变量 'a' 进行更改,并且此更改是全局可见的。

【问题讨论】:

    标签: python python-3.x python-import


    【解决方案1】:

    你把事情复杂化了。从导入的角度来看,唯一要知道的是import foo将foo带入当前命名空间,from foo import bar将bar带入当前命名空间。

    【讨论】:

    • 在您的示例中,假设 foo 有一个变量 bar=10。当我们使用 [import foo] 时 - 正如您所说,这会将 foo 带入当前命名空间并允许我们通过 foo.bar 更改 bar 的值,并且此更改对使用 [import foo print(foo .bar)] 完成上述分配后。在 [from foo import bar] 的情况下,对 bar 所做的任何更改仅对该模块可见,而不是任何其他模块,无论它们是否执行 [import foo] 或 [from foo import bar]。所以我想从这个上下文中理解
    • 但这又与 Python 中的任何其他内容完全相同。如果您有一个类实例foo,然后执行foo.bar = 1,那么对foo 的任何其他引用也将看到新属性;而如果你像foo = 1 那样重新分配 foo,那只会影响它在本地命名空间中绑定的内容。这就是名称在 Python 中的工作方式,与导入或模块无关。
    • 您可能应该阅读这篇有用的帖子:nedbatchelder.com/text/names.html
    • 你能不能给我指出一篇解释命名空间生命周期的文章(从“导入”/“从导入”的角度来看)-我的困惑是因为-同时使用-a)' import modulename' 和 b) 'from modulename import fn/var' 这两种方法都使整个模块代码运行,但在调用者中,只有方法 'a' 提供对被调用模块命名空间的引用。而方法 'b' 没有给出任何参考,而是 fn/var 的副本。
    • 我不知道有什么特别的,但我不确定还有什么要说的。 Python 必须执行一个模块才能从中导入东西,否则它怎么知道要导入什么?正如您所说,唯一的区别是在当前命名空间中获得引用。
    【解决方案2】:

    Python 只有 3 个作用域:全局本地和内置。
    它们是相对于代码中的位置

    您可以更改其值的每个变量都是本地变量
    (请注意,更改全局变量会导致创建新的局部变量,
    所以有同名的局部变量和全局变量)
    您所说的附件是该功能的本地文件

    每一个内容不变的变量,你能得到的值都是全局的

    内置变量与全局变量完全相同,因此它们甚至可以被视为全局变量

    要查看哪些变量是全局变量,哪些变量是本地变量,请将此行放入您的代码中
    print("global:", globals(), "\n\nlocal:", locals())

    【讨论】:

      猜你喜欢
      • 2013-08-11
      • 1970-01-01
      • 2014-12-02
      • 1970-01-01
      • 2012-12-28
      • 1970-01-01
      • 1970-01-01
      • 2012-01-11
      • 1970-01-01
      相关资源
      最近更新 更多