我有一个模块foo.py
,我正在将其导入文件main.py
,在imports
的顶部有foo.py
,例如import numpy as np
,等等
现在,如果我只调用某个函数fun(arg1, arg2, arg3)
,请执行imports
顶部的foo.py
还是必须在函数内部添加imports
fun
的定义?
在这方面,from foo import fun
和import 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
答案 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)
首次加载模块时,模块中的所有行都将运行。 import
,def
,常规分配等。所有这些行都会初始化作为模块对象的名称空间。 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