应该导入Python类内部还是外部?

时间:2014-09-03 17:55:35

标签: python

概述

假设我正在构建一个用于一般用法的类:我可能需要在任何地方导入它,在其他几个文件中使用它等等。如果导入在课前进行,则为:

import foo

class Bar():

    def __init__(self):
        foo.spam()

或在__init__方法内,如:

class Bar():

    def __init__(self):

        import foo

        foo.spam()

我的分析

+将foo带入全局命名空间,以便在整个Bar

中使用

- 导入Bar还需要您手动导入foo (@MartijnPieters

+在实际需要之前避免加载foo

实例foo

导入(和使用)(@BrenBarn)时加载

+ Bar

- foo在其他地方无法使用

2 个答案:

答案 0 :(得分:3)

通常所有导入都位于模块的顶部。通过目视检查或像pyflakes这样的代码检查器,可以很容易地一目了然地看到模块的依赖关系。您假设"导入Bar还要求您手动导入foo"是假的。

在函数或方法内部导入的唯一时间是导入非常耗费资源(例如,速度慢)或不可靠(例如,可能未安装的可选依赖项,特定于平台的模块或模块往往会破坏),客户端代码不应总是调用有问题的函数。

答案 1 :(得分:2)

有一些相关问题herehere等。最重要的是,除非你有充分和特殊的理由不这样做,否则通常最好将所有进口放在最顶层。

至于你的分析:

  

导入栏还要求您手动导入foo

没有。导入栏将自动导入foo,无论其他代码是什么,Bar都可以使用foo。 Imports仅在执行导入的模块内创建对导入模块的引用(即,它们不会使导入的名称在所有模块中“全局可用”)。

  
      导入(和使用)Bar时
  • foo加载
  •   

请注意,“导入”和“使用”不是一回事。在您的示例中,当实例化(使用foo)时,将导入Bar(),因为它位于__init__方法中。导入Bar时不会加载它。

  
      
  • 在实际需要之前避免加载foo
  •   

这是事实,但在实践中它通常会让你失望。如果使用您的模块的人有可能不需要使用导入foo的部分(即Bar),则有必要担心这一点。即使这样,只有导入foo缓慢,资源密集或有时可能无效(例如,如果foo是一个可能并非在所有平台上都可用的库),这才有意义。对于大多数模块,通过推迟导入,您获得的收益很少。

这提出了一个不做本地导入的重要原因:它使得更难以了解模块的依赖性。能够查看模块顶部并查看导入所需的所有内容非常方便。如果关键导入隐藏在代码深处,则更难理解其他模块需要什么。