【问题标题】:What are `globals` and `locals` parameters in Python __import__ function for?Python __import__ 函数中的 `globals` 和 `locals` 参数有什么用?
【发布时间】:2011-02-02 09:15:27
【问题描述】:

Python文档中有__import__的一部分,看不懂:

__import__(name[, globals[, locals[, fromlist[, level]]]])

该函数导入模块name,可能使用给定的globalslocals 来确定如何在包上下文中解释name。标准实现根本不使用其locals 参数,而仅使用其globals 来确定导入语句的包上下文。

对模块名称有什么“解释”?什么是包上下文?

使用这些参数的示例调用如下所示:

spam = __import__('spam', globals(), locals(), [], -1)

为什么示例向函数提供globals()locals()?当我只提供globals() 时会发生什么?或者两者都不是?

我可能缺少与导入模块相关的命名空间逻辑的某些部分。你能给我指出一篇解释这个/有__import__函数示例的文章吗?

【问题讨论】:

  • 这个问题不应该移到 StackOverflow 上吗?
  • 这很有趣,我开始在 SO 上写这个,但我正在考虑是否应该将它发布在programmers.SE 上...我显然需要查看常见问题解答...
  • 您应该选择以下答案之一作为此问题的可接受答案。恕我直言,9000 的回答一针见血,解释了 Python 对 globals 的作用以确定模块命名空间。

标签: python import


【解决方案1】:

标准实现根本不使用其locals 参数,而仅使用其globals 来确定@​​987654324@ 语句的包上下文。

(来自docs.python.org

我还是不知道globals是怎么用的;什么全局变量会影响import 语句的工作方式?

编辑:在查看 Python 2.5 源代码中的 import.c 后,我发现 __import__ 期望在 globals 中找到 __name____path__ 以增加导入搜索路径相对于在这些变量之一中找到的路径,按此顺序。

【讨论】:

  • 谈钝。所以基本上,与其传递包含所有全局变量的大量内存(假设 Python 不通过引用来实现),不如简单地传递一个带有单个键的字典,"__name__",设置为调用模块的@987654333 @ 属性,Python 将使用它。 Python 文档应该使用这些信息进行更新。
  • @Kumba:假设 Python 通过引用完成大多数事情,除了一些原始的数字操作。字典肯定是通过引用传递的。 Python 3.3 甚至引入了共享键的字典实现,也就是说,键也可以通过引用来访问。如果您想抱怨,请谈论缓存一致性:)
  • 实际上玩过(并拥有)非缓存一致的硬件,我只能开始想象那个噩梦。值得庆幸的是(或者遗憾的是,任您选择),我用 Python 编写的代码至少必须在 Python 2.4 上运行。我避免使用 3.x,因为我知道它完全颠覆了语言,而且我的很多代码如果不认真重写可能就无法工作。
【解决方案2】:

globals 用于确定调用导入的当前上下文。例如:

"""
/myproject/a/b.py
/myproject/a/foo.py
/myproject/c/d.py
/myproject/c/foo.py
"""

# Which foo gets imported?

import foo #1
foo = __import__('foo') #2

它们不一样,因为在#2 上没有(简单的)方法可以知道从哪个模块调用导入。 __import__ 函数需要知道哪个是当前模块才能真正导入正确的foo

__import__() 内部,globals 用于获取调用导入的当前模块的引用。来自__import__source code

返回正在执行导入的包。如果全局变量来了 从模块 foo.bar.bat (本身不是一个包),这将返回 foo.bar 的 sys.modules 条目。如果全局变量来自包的 init.py, sys.modules 中的包条目作为借用引用返回。

【讨论】:

  • 假设b.pyd.py 中有import foo。 Python 怎么不知道要导入哪一个?如果是b.py,为什么会在../c/中寻找foo
  • 如果/myproject/e.py 中有import foo,那应该不行。 import a.fooimport c.foo。对不起...我似乎无法举出会“引起麻烦”的例子,你能给我一个提示吗?
【解决方案3】:

关于模块名称有什么可以“解释”的?什么是包上下文?

当你进入

>>> a

Python 必须“解释”该名称。是全球性的吗?是本地人吗?

>>> def f(x):
...    return x * a

现在,x 显然是本地的。 a 必须被“解释”。全球的?本地?

为什么该示例为函数提供 globals() 和 locals()?当我只提供 globals() 时会发生什么?还是两者都没有?

试试看。严重地。玩起来比问起来容易。

重要的是您在>>> 提示符下所做的事情是全局性的。

您需要定义将创建本地上下文的函数,以便查看全局和本地之间的差异。

【讨论】:

  • 残酷^W 有趣的事实是,被导入的模块几乎忽略了执行导入的模块的全局值,而__import__ 完全忽略了locals 参数。否则,你是对的:)
猜你喜欢
  • 2014-06-01
  • 2011-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-18
  • 1970-01-01
  • 2015-05-18
  • 1970-01-01
相关资源
最近更新 更多