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

当前回答

大多数情况下,这对于清晰和明智的做法是有用的,但并不总是如此。下面是模块导入可能存在于其他地方的两个例子。

首先,你可以有一个这样的单元测试模块:

if __name__ == '__main__':
    import foo
    aa = foo.xyz()         # initiate something for the test

其次,您可能需要在运行时有条件地导入一些不同的模块。

if [condition]:
    import foo as plugin_api
else:
    import bar as plugin_api
xx = plugin_api.Plugin()
[...]

在其他情况下,您可能会在代码的其他部分导入。

其他回答

这是一个只有程序员才能决定的权衡。

Case 1在需要时才导入datetime模块(并进行任何可能需要的初始化),从而节省了一些内存和启动时间。请注意,“仅在被调用时”导入也意味着“每次被调用时”导入,因此第一次调用之后的每个调用仍然会产生执行导入的额外开销。

情况2通过提前导入datetime来节省一些执行时间和延迟,这样在调用not_often_called()时就会更快地返回,而且也不会在每次调用时都产生导入的开销。

除了效率,如果import语句是…前面。将它们隐藏在代码中会使查找某个组件所依赖的模块变得更加困难。

就我个人而言,我通常遵循PEP,除了单元测试之类的东西,我不希望总是加载这些东西,因为我知道除了测试代码之外,它们不会被使用。

可读性

除了启动性能外,本地化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版本号,因此在文件顶部导入会引入不必要的启动延迟。

虽然PEP鼓励在模块顶部导入,但在其他级别导入并不会出错。这表明进口应该在顶部,但也有例外。

在使用模块时加载模块是一种微优化。导入缓慢的代码可以在以后进行优化,如果这会产生相当大的差异的话。

不过,您可以在尽可能靠近顶部的位置引入标志,以便有条件地导入,允许用户使用配置导入所需的模块,同时仍然立即导入所有内容。

尽快导入意味着如果任何导入(或导入的导入)缺失或有语法错误,程序将失败。如果所有导入都发生在所有模块的顶部,则python分两步工作。编译。运行。

内置模块可以在任何导入它们的地方工作,因为它们设计得很好。您编写的模块应该是相同的。将导入移动到顶部或它们的第一次使用位置有助于确保没有副作用,并且代码正在注入依赖项。

无论您是否将导入放在顶部,当导入放在顶部时,代码都应该仍然可以工作。所以从立即导入开始,然后根据需要进行优化。

下面是一个示例,其中所有导入都位于最顶部(这是我唯一一次需要这样做)。我希望能够在Un*x和Windows上终止子进程。

import os
# ...
try:
    kill = os.kill  # will raise AttributeError on Windows
    from signal import SIGTERM
    def terminate(process):
        kill(process.pid, SIGTERM)
except (AttributeError, ImportError):
    try:
        from win32api import TerminateProcess  # use win32api if available
        def terminate(process):
            TerminateProcess(int(process._handle), -1)
    except ImportError:
        def terminate(process):
            raise NotImplementedError  # define a dummy function

(回顾:约翰·米利金所说。)

I do not aspire to provide complete answer, because others have already done this very well. I just want to mention one use case when I find especially useful to import modules inside functions. My application uses python packages and modules stored in certain location as plugins. During application startup, the application walks through all the modules in the location and imports them, then it looks inside the modules and if it finds some mounting points for the plugins (in my case it is a subclass of a certain base class having a unique ID) it registers them. The number of plugins is large (now dozens, but maybe hundreds in the future) and each of them is used quite rarely. Having imports of third party libraries at the top of my plugin modules was a bit penalty during application startup. Especially some thirdparty libraries are heavy to import (e.g. import of plotly even tries to connect to internet and download something which was adding about one second to startup). By optimizing imports (calling them only in the functions where they are used) in the plugins I managed to shrink the startup from 10 seconds to some 2 seconds. That is a big difference for my users.

所以我的答案是否定的,不要总是把导入放在模块的顶部。