当我们仅从模块顶部调用函数时,是否会导入模块顶部的软件包?

时间:2019-06-17 06:28:46

标签: python python-import python-module

我有一个模块foo.py,我正在将其导入文件main.py,在imports的顶部有foo.py,例如import numpy as np,等等 现在,如果我只调用某个函数fun(arg1, arg2, arg3),请执行imports顶部的foo.py还是必须在函数内部添加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

3 个答案:

答案 0 :(得分:2)

否,您不需要再次将其导入fun中。您可以对此进行测试,即使您在numpy的顶部仅导入一次foo.py,您的代码也可以正常工作。

这两种方法没有什么区别,除了如果您导入为import foo,您必须将fun称为foo.fun。如果您改为使用from foo import fun,则可以只使用fun

导入模块时,python将执行模块文件中的所有语句。因此,以上述两种方式之一导入foo时,它将运行import numpy as np并更新foo的私有符号表。 foo中定义的所有语句和函数都可以使用此表中的符号,而无需任何限定。对于您来说,fun将以numpy的身份访问np

numpy导入本身会发生什么有趣的事情。

案例1

from foo import fun

您仅导入了fun以外的任何内容。由于上述原因,fun中的任何代码都可以运行,但是np本身对于main中的代码而言是不可见的。

案例2

import foo

在这里,您将像我之前所说的那样将fun称为foo.fun,但是np也可以用作foo.np,但是绝对不建议这样做。

如果要在当前文件中使用模块,总是最好再次导入模块,不要依赖于从其他文件间接导入。由于python会缓存导入,因此您无需担心性能或循环导入。

阅读import system,以全面了解所有内容。

答案 1 :(得分:1)

首次加载模块时,模块中的所有行都将运行。 importdef,常规分配等。所有这些行都会初始化作为模块对象的名称空间。 foo的命名空间将具有指向加载的numpy模块的变量np和指向函数对象的变量fun

函数是python中的一流对象。特别是,它们具有一个__globals__(在链接的docs中的“ Callable Types”下查找)属性,该属性指向定义它们的模块的名称空间。无论您对{{1 }},名称foo.fun将在函数中可用,直到您从np本身将其删除。

不建议您在函数内部导入任何内容,除非您有充分的理由这样做,例如避免使用全局名称。在您foo一个模块时,解释器将首先查看import。如果找到它,sys.modules所花费的时间不会比对全局字典的查找长得多。但是,如果尚未加载该模块,则将立即加载该模块。您可能不希望在程序中的任意位置产生这种开销,尤其是那些可能对时间敏感的开销。

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

TL; DR

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

答案 2 :(得分:0)

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

有关更多信息,请检查此 Which is a better practice - global import or local import