Python中的好或坏实践:在文件中间导入

Python中的好或坏实践:在文件中间导入,python,python-import,Python,Python Import,假设我有一个相对较长的模块,但只需要一次外部模块或方法 在模块中间导入该方法或模块是否正确? 或者,imports应仅位于模块的第一部分 例如: import string, pythis, pythat ... ... ... ... def func(): blah blah blah from pysomething import foo foo() etc etc etc ... ... ... 请证明

假设我有一个相对较长的模块,但只需要一次外部模块或方法

在模块中间导入该方法或模块是否正确?

或者,
import
s应仅位于模块的第一部分

例如:

import string, pythis, pythat
...
...
...
...
def func():
     blah
     blah 
     blah
     from pysomething import foo
     foo()
     etc
     etc 
     etc
...
...
...
请证明您的答案,并添加指向s或相关来源的链接

在文件开头将所有导入分组被认为是“好形式”

模块可以导入其他模块。通常,但不要求将所有导入语句放在模块(或脚本)的开头。导入的模块名称放置在导入模块的全局符号表中


从这里开始:

这通常被认为是不好的做法,但有时这是不可避免的(比如当您必须避免循环导入时)

一个有必要的时候的例子:我用它来构建我们所有的代码。系统分为多个工具,每个工具都在自己的模块中实现。每个工具模块都可以执行
detect()
方法来检测前提条件是否存在。其中一个示例可以执行以下操作:

def detect(self):
    import foobar
如果工作正常,则该工具可用。随后在同一模块中可能需要
foobar
模块,因此您必须在功能级别范围内再次导入它。显然,如果它是在模块级导入的,事情就会完全爆炸。

权威性地指出:

进口总是放在最重要的位置 该文件位于任何模块之后 注释和文档字符串,以及模块全局变量和常量之前


PEP 8应该是任何“内部”风格指南的基础,因为它总结了核心Python团队发现的总体上最有效的风格(当然,与任何其他语言一样,也有个人的不同意见,但共识和BDFL同意PEP 8)。

如果导入的模块很少使用,并且导入成本高昂,中间的导入是可以的

否则,听从亚历克斯·马尔泰利的建议是否明智。:

进口总是放在最重要的位置 该文件位于任何模块之后 注释和文档字符串,以及模块全局变量和常量之前

对进口产品进行范围界定并不是一种坏做法。这样导入只应用于您在其中使用它的函数


我认为,如果导入在块的顶部组合在一起,或者如果您希望它全局地位于文件的顶部,那么代码的可读性会更好

好的,我认为在文件开始时将所有导入分组是一个好的做法,因为如果每个人都想知道加载了哪些lib,那么他们都知道应该去哪里查看在2001年的Python邮件列表中详细讨论了这个主题:

下面是该线程中讨论的一些原因。彼得·汉森(Peter Hansen)指出,有三个理由不将导入全部放在文件顶部:

在函数中导入的可能原因:

  • 可读性:如果只需要在一个 功能是不可能改变的, 只放在那里可能会更清楚更干净

  • 启动时间:如果没有外部导入 在函数定义中,它不会执行 当您的模块第一次由另一个导入时 仅当调用其中一个函数时。这 延迟导入的开销(或避免导入) 如果函数可能永远不会被调用)

  • 总有一个原因比另一个多 到现在为止,我们一直在考虑这个问题

  • 只是范罗瑟姆插话说了第四句:

  • 开销:如果模块导入了很多模块, 而且很有可能只有少数人会 被使用。这类似于“启动时间” 原因,但更进一步。如果是脚本 使用您的模块仅使用一小部分 它可以节省相当多的时间,尤其是 如果可以避免的进口也会进口很多 模块的数量
  • 第五种是因为本地进口是避免循环进口问题的一种方式


    请随意阅读该主题以进行完整的讨论。

    95%的时候,您应该将所有导入内容放在文件的顶部。在一种情况下,如果为了避免循环导入而必须进行函数本地导入,则可能需要这样做。假设foo.py导入bar.py,则bar.py中的函数需要从foo.py导入某些内容。如果将所有导入放在顶部,则导入依赖于尚未编译的信息的文件时可能会出现意外问题。在这种情况下,使用函数本地导入可以使您的代码推迟导入另一个模块,直到其代码完全编译完毕,并且您调用相关函数

    然而,看起来您的用例更多的是为了明确foo()的来源。在这种情况下,我更喜欢两件事中的一件:

    首先,而不是

    from prerequisite import foo
    
    直接导入先决条件,然后将其称为prerequisite.foo。通过增加代码的透明度,增加的冗长会得到回报


    或者,(或者结合上述内容)如果您的导入和使用位置之间的距离真的很长,则可能是您的模块太大。对一个没有其他用途的导入的需求可能是一个指示,你的代码可能会被重构成一个更易于管理的块。

    每个人都已经提到了PPEs,但也要注意<强> > < >强>在临界代码中间有导入语句。至少在Python2.6中,当一个函数有一个import语句时,还需要几个字节码指令

    >>> def f():
        from time import time
        print time()
    
    >>> dis.dis(f)
      2           0 LOAD_CONST               1 (-1)
                  3 LOAD_CONST               2 (('time',))
                  6 IMPORT_NAME              0 (time)
                  9 IMPORT_FROM              0 (time)
                 12 STORE_FAST               0 (time)
                 15 POP_TOP             
    
      3          16 LOAD_FAST                0 (time)
                 19 CALL_FUNCTION            0
                 22 PRINT_ITEM          
                 23 PRINT_NEWLINE       
                 24 LOAD_CONST               0 (None)
                 27 RETURN_VALUE
    
    >>> def g():
        print time()
    
    >>> dis.dis(g)
      2           0 LOAD_GLOBAL              0 (time)
                  3 CALL_FUNCTION            0
                  6 PRINT_ITEM          
                  7 PRINT_NEWLINE       
                  8 LOAD_CONST               0 (None)
                 11 RETURN_VALUE  
    

    亚历克斯:这是“最佳实践”,但并非总是可以避免的。请看我上面给出的例子。@jkp,S.Lott对您的答案进行了评论,并说明了原因