从模块导入函数在 Python 中如何工作?

How does importing a function from a module work in Python?

我有一个模块 some_module.py,其中包含以下代码:

def testf():
    print(os.listdir())

现在,在名为 test.py 的文件中,我有以下代码:

import os
from some_module import testf

testf()

但是执行 test.py 会得到 NameError: name 'os' is not defined。我已经在 test.py 中导入了 os,并且 testftest.py 的命名空间中。那么为什么会出现这个错误呢?

名称 testftest 的命名空间中。 testf 函数的 内容 仍在 some_module 中,无法访问 test.

中的任何内容

如果您有需要模块的代码,则需要将该模块导入该代码所在的同一文件中。导入模块只会将它导入到您导入它的那个文件中。 (在不同的文件中多次导入同一个模块,不会产生有意义的性能损失;模块的实际加载只发生一次,稍后导入同一个模块只是获得对已导入模块的引用。)

导入模块会将其名称添加为 current 范围的属性。由于不同的模块具有独立的作用域,some_module 中的任何代码都不能使用 __main__(执行的脚本)中的名称,除非先导入它。

import 与包含文件内容不同,就好像您直接键入它来代替 import 语句一样。如果您来自 C 背景,您可能会认为它以这种方式工作,其中 #include 预处理器指令执行此操作,但 Python 不同。

Python 中的 import 语句读取正在导入的文件的内容并在其自己单独的上下文中对其进行评估 - 因此,在您的示例中,some_module.py 中的代码具有无法访问或了解 test.py 或任何其他文件中存在的任何内容。它以 "blank slate" 开头,可以这么说。如果 some_module.py 的代码要访问 os 模块,则必须在 some_module.py.

的顶部导入它

当模块在 Python 中导入时,它变成了一个 对象 。也就是说,当你写

import some_module

Python 做的第一件事就是创建一个 module 类型的新对象来表示正在导入的模块。当解释器遍历 some_module.py 中的代码时,它会将在该文件中定义的任何变量、函数、类 等分配为这个新模块对象的属性。因此在您的示例中,模块对象将具有一个属性 testf。当函数 testf 中的代码想要访问变量 os 时,它会查看函数本身(本地作用域)并发现 os 未在此处定义,因此它会查看testf 所属的模块对象的属性(这是 "global" 范围,尽管它不是真正的全局)。在您的示例中,它不会在那里看到 os,因此您会收到错误消息。如果你添加

import os

some_module.py,然后将在名称 os 下创建模块的属性,您的代码将找到它需要的内容。

您可能还对我写的一些其他答案感兴趣,这些答案可能有助于您理解 Python 的 import 声明:

  • Why import when you need to use the full name?