PEP 8规定:

导入总是放在文件的顶部,就在任何模块注释和文档字符串之后,在模块全局变量和常量之前。

然而,如果我导入的类/方法/函数只在很少的情况下使用,那么在需要时进行导入肯定会更有效吗?

这不是:

class SomeClass(object):

    def not_often_called(self)
        from datetime import datetime
        self.datetime = datetime.now()

比这更有效率?

from datetime import datetime

class SomeClass(object):

    def not_often_called(self)
        self.datetime = datetime.now()

当前回答

为了完成老谋子的回答和最初的问题:

当我们不得不处理循环依赖关系时,我们可以做一些“技巧”。假设我们正在处理模块a.py和b.py,它们分别包含x()和b.y()。然后:

我们可以移动模块底部的from导入之一。 我们可以将其中一个from导入移动到实际需要导入的函数或方法中(这并不总是可行的,因为您可能从多个地方使用它)。 我们可以把其中一个import改成import,就像import a

总结一下。如果您没有处理循环依赖关系,也没有使用某种技巧来避免它们,那么最好将所有导入放在顶部,因为原因已经在这个问题的其他答案中解释过了。请在做这些“技巧”时附上评论,这总是受欢迎的!:)

其他回答

我想提一下我的一个用例,与@John Millikin和@ v.k.提到的用例非常相似:

可选的进口

我使用Jupyter Notebook进行数据分析,我使用相同的IPython Notebook作为所有分析的模板。在某些情况下,我需要导入Tensorflow来做一些快速的模型运行,但有时我工作的地方,Tensorflow没有设置/导入很慢。在这些情况下,我将依赖于tensorflow的操作封装在一个helper函数中,在该函数中导入tensorflow,并将其绑定到一个按钮。

这样,我就可以“重新启动并运行全部”,而不必等待导入,也不必在导入失败时恢复其余的单元格。

当函数被调用0次或1次时,第一种变体确实比第二种更有效。然而,对于第二次和后续调用,“导入每个调用”方法实际上效率较低。请参阅此链接,了解一种通过“惰性导入”将两种方法的优点结合起来的惰性加载技术。

但除了效率之外,还有其他原因可以解释为什么你会更喜欢其中一种。一种方法是让阅读代码的人更清楚地了解这个模块所具有的依赖关系。它们也有非常不同的失败特征——如果没有“datetime”模块,第一个将在加载时失败,而第二个直到方法被调用才会失败。

补充说明:在IronPython中,导入可能比在CPython中要昂贵一些,因为代码基本上是在导入时被编译的。

我采用了将所有导入放在使用它们的函数中,而不是放在模块的顶部的做法。

这样做的好处是能够更可靠地进行重构。当我将一个函数从一个模块移动到另一个模块时,我知道该函数将继续工作,并且保留所有遗留的测试。如果我将导入放在模块的顶部,当我移动一个函数时,我发现我最终要花费大量时间来完成新模块的导入并使其最小化。重构IDE可能会让这一点变得无关紧要。

正如在其他地方提到的那样,有一个速度惩罚。我在我的应用程序中测量了这一点,发现它对我的目的来说是微不足道的。

不需要搜索(例如grep)就能看到所有模块依赖关系也是很好的。然而,我关心模块依赖关系的原因通常是因为我正在安装、重构或移动由多个文件组成的整个系统,而不仅仅是单个模块。在这种情况下,我无论如何都要执行全局搜索,以确保具有系统级依赖关系。因此,我还没有找到全局导入来帮助我在实践中理解一个系统。

我通常把sys的导入放在if __name__=='__main__'检查中,然后将参数(如sys.argv[1:])传递给main()函数。这允许我在sys未被导入的上下文中使用main。

Putting the import statement inside of a function can prevent circular dependencies. For example, if you have 2 modules, X.py and Y.py, and they both need to import each other, this will cause a circular dependency when you import one of the modules causing an infinite loop. If you move the import statement in one of the modules then it won't try to import the other module till the function is called, and that module will already be imported, so no infinite loop. Read here for more - effbot.org/zone/import-confusion.htm

可读性

除了启动性能外,本地化import语句还需要考虑可读性。例如,在我目前的第一个python项目中使用python行号1283到1296:

listdata.append(['tk font version', font_version])
listdata.append(['Gtk version', str(Gtk.get_major_version())+"."+
                 str(Gtk.get_minor_version())+"."+
                 str(Gtk.get_micro_version())])

import xml.etree.ElementTree as ET

xmltree = ET.parse('/usr/share/gnome/gnome-version.xml')
xmlroot = xmltree.getroot()
result = []
for child in xmlroot:
    result.append(child.text)
listdata.append(['Gnome version', result[0]+"."+result[1]+"."+
                 result[2]+" "+result[3]])

如果import语句在文件的顶部,我将不得不向上滚动很长一段距离,或按Home键,以找出ET是什么。然后我将不得不返回到第1283行继续阅读代码。

实际上,即使import语句像许多人那样位于函数(或类)的顶部,也需要向上和向下分页。

很少会显示Gnome版本号,因此在文件顶部导入会引入不必要的启动延迟。