当我们只从该模块调用函数时,是否导入模块顶部的包

Do packages at the top of a module get imported when we are only calling a function from that module

我有一个模块 foo.py,我正在将其导入我的文件 main.py,我在 foo.py 的顶部有 imports,例如 import numpy as np, ETC。 现在,如果我只调用某个函数 fun(arg1, arg2, arg3),是 foo.py 顶部的 imports 发生还是我必须在函数内添加 imports fun的定义?

另外,在这方面 from foo import funimport foo 有区别吗?

文件foo.py(待导入)

import numpy as np

def fun(arg1, arg2, arg3):
    x = np.argsort(arg1)
    return x

文件main.py

import foo

call = fun([2, 34, 0, -1], 4, 5])

或者我应该在 foo.py 中使用这个吗?

def fun(arg1, arg2, arg3):
   import numpy as np
   x = np.argsort(arg1)
   return x

不,您不需要在 fun 中再次导入它。您可以对此进行测试,即使您的 import numpy 仅在 foo.py.

的顶部出现一次,您的代码也应该可以正常工作

这两种方式没有任何区别,只是如果您导入为 import foo,则必须将 fun 引用为 foo.fun。如果您改为 from foo import fun,则只需使用 fun.

导入模块时,python会执行模块文件中的所有语句。因此,当您以上述两种方式之一导入 foo 时,它将 运行 import numpy as np 并更新私有符号 table 为 foo。所有在 foo 中定义的语句、函数都可以在这个 table 中使用符号而无需任何限定。在您的情况下,fun 将作为 np.

访问 numpy

numpy import 本身发生了什么更有趣。

案例一

from foo import fun

您只导入 fun 没有别的。由于上述原因,fun 中的任何代码都将 运行,但 np 本身对 main.

中的代码不可见

案例二

import foo

这里你会把fun当成我之前说的foo.fun,但是np也可以当成foo.np,但是绝对不推荐。

如果要在当前文件中使用它们,最好再次导入模块,不要依赖从其他文件间接导入。因为,python 缓存导入,您不必担心性能或循环导入。

阅读 import system 以充分理解这一切。

第一次加载模块时,里面的所有行都是运行。 imports、defs、常规赋值等。所有这些行都初始化了一个作为模块对象的命名空间。 foo 的命名空间将有一个变量 np 指向加载的 numpy 模块,以及一个变量 fun 指向你的函数对象。

函数是 python 中的第一个 class 个对象。特别是,它们有一个 __globals__(在链接文档中的 "Callable Types" 下查看)属性,它指向定义它们的模块的名称空间。无论您对 [= 的引用做什么16=],名称 np 将在函数中可用,直到您将其从 foo 本身删除。

不建议您在函数中导入任何内容,除非您有充分的理由这样做,例如避免使用全局名称。当你 import 一个模块时,解释器会首先查看 sys.modules。如果找到,import 不会比查找全局字典花费更多的时间。但是,如果模块尚未加载,它会立即加载。您可能不希望在程序中的任意点产生这种开销,尤其是 time-sensitive.

就导入形式而言,差异主要是美学上的,但它们也有实际影响。 from foo import fun 在您的命名空间中创建一个名称 fun,直接引用感兴趣的函数对象。它会用一个额外的名称污染您的本地名称空间,但每次您访问该函数时,您都可以通过 foo 的名称空间字典进行查找。另一方面,import foo 可以很好地捆绑所有内容,因为您必须调用 foo.fun,但这需要额外的查找。

TL;DR

您应该将所有导入内容放在文件的顶部。你怎么做并不重要。

不需要在函数 fun() 中再次导入它。

更多信息,请查看这里 Which is a better practice - global import or local import