假设我正在构建一个用于一般用法的类:我可能需要在任何地方导入它,在其他几个文件中使用它等等。如果导入在课前进行,则为:
import foo
class Bar():
def __init__(self):
foo.spam()
或在__init__
方法内,如:
class Bar():
def __init__(self):
import foo
foo.spam()
+将foo
带入全局命名空间,以便在整个Bar
- 导入(@MartijnPieters 等)Bar
还需要您手动导入foo
+在实际需要之前避免加载foo
foo
导入(和使用)(@BrenBarn)时加载
+ Bar
- foo
在其他地方无法使用
答案 0 :(得分:3)
通常所有导入都位于模块的顶部。通过目视检查或像pyflakes这样的代码检查器,可以很容易地一目了然地看到模块的依赖关系。您假设"导入Bar
还要求您手动导入foo
"是假的。
在函数或方法内部导入的唯一时间是导入非常耗费资源(例如,速度慢)或不可靠(例如,可能未安装的可选依赖项,特定于平台的模块或模块往往会破坏),客户端代码不应总是调用有问题的函数。
答案 1 :(得分:2)
有一些相关问题here和here等。最重要的是,除非你有充分和特殊的理由不这样做,否则通常最好将所有进口放在最顶层。
至于你的分析:
导入栏还要求您手动导入foo
没有。导入栏将自动导入foo,无论其他代码是什么,Bar都可以使用foo。 Imports仅在执行导入的模块内创建对导入模块的引用(即,它们不会使导入的名称在所有模块中“全局可用”)。
导入(和使用)Bar时
- foo加载
请注意,“导入”和“使用”不是一回事。在您的示例中,当实例化(使用foo
)时,将导入Bar()
,因为它位于__init__
方法中。导入Bar时不会加载它。
- 在实际需要之前避免加载foo
这是事实,但在实践中它通常会让你失望。如果使用您的模块的人有可能不需要使用导入foo
的部分(即Bar
),则有必要担心这一点。即使这样,只有导入foo
缓慢,资源密集或有时可能无效(例如,如果foo
是一个可能并非在所有平台上都可用的库),这才有意义。对于大多数模块,通过推迟导入,您获得的收益很少。
这提出了一个不做本地导入的重要原因:它使得更难以了解模块的依赖性。能够查看模块顶部并查看导入所需的所有内容非常方便。如果关键导入隐藏在代码深处,则更难理解其他模块需要什么。