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()

当前回答

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

其他回答

有趣的是,到目前为止,没有一个回答提到并行处理,当序列化的函数代码被推到其他核心时,可能需要将导入放在函数中,例如在ipyparallel的情况下。

这就像许多其他优化一样——你牺牲了一些可读性来换取速度。正如John提到的,如果您已经完成了分析作业,并且发现这是一个非常有用的更改,并且您需要额外的速度,那么就去做吧。最好把所有其他的导入都放在一起:

from foo import bar
from baz import qux
# Note: datetime is imported in SomeClass below

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

可选的进口

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

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

我很惊讶没有看到重复负载检查的实际成本数字,尽管有很多很好的解释。

如果你在顶部导入,不管发生什么,你都要加载命中。这非常小,但通常是毫秒级,而不是纳秒级。

If you import within a function(s), then you only take the hit for loading if and when one of those functions is first called. As many have pointed out, if that doesn't happen at all, you save the load time. But if the function(s) get called a lot, you take a repeated though much smaller hit (for checking that it has been loaded; not for actually re-loading). On the other hand, as @aaronasterling pointed out you also save a little because importing within a function lets the function use slightly-faster local variable lookups to identify the name later (http://stackoverflow.com/questions/477096/python-import-coding-style/4789963#4789963).

下面是一个简单测试的结果,该测试从函数内部导入了一些内容。报告的时间(在2.3 GHz Intel Core i7上的Python 2.7.14中)如下所示(第2个调用比后面的调用多似乎是一致的,尽管我不知道为什么)。

 0 foo:   14429.0924 µs
 1 foo:      63.8962 µs
 2 foo:      10.0136 µs
 3 foo:       7.1526 µs
 4 foo:       7.8678 µs
 0 bar:       9.0599 µs
 1 bar:       6.9141 µs
 2 bar:       7.1526 µs
 3 bar:       7.8678 µs
 4 bar:       7.1526 µs

代码:

from __future__ import print_function
from time import time

def foo():
    import collections
    import re
    import string
    import math
    import subprocess
    return

def bar():
    import collections
    import re
    import string
    import math
    import subprocess
    return

t0 = time()
for i in xrange(5):
    foo()
    t1 = time()
    print("    %2d foo: %12.4f \xC2\xB5s" % (i, (t1-t0)*1E6))
    t0 = t1
for i in xrange(5):
    bar()
    t1 = time()
    print("    %2d bar: %12.4f \xC2\xB5s" % (i, (t1-t0)*1E6))
    t0 = t1

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

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

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

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