代码之家  ›  专栏  ›  技术社区  ›  flybywire

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

  •  52
  • flybywire  · 技术社区  · 15 年前

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

    在模块中间导入该方法或模块是否可以?

    或者应该 import S只在模块的第一部分。

    例子:

    import string, pythis, pythat
    ...
    ...
    ...
    ...
    def func():
         blah
         blah 
         blah
         from pysomething import foo
         foo()
         etc
         etc 
         etc
    ...
    ...
    ...
    

    请证明您的答案,并添加链接到 PEP S或相关来源

    9 回复  |  直到 7 年前
        1
  •  53
  •   Kamaraju Kusumanchi    7 年前

    PEP 8 授权声明:

    进口总是放在 文件,在任何模块之后 注释和文档字符串,以及模块全局和常量之前。

    PEP8应该是任何“内部”风格指南的基础,因为它总结了核心python团队发现的最有效的整体风格(当然也包括个人异议,如任何其他语言,但共识和BDFL同意PEP8)。

        2
  •  17
  •   shakaran    9 年前

    2001年在python邮件列表中详细讨论了这个主题:

    https://mail.python.org/pipermail/python-list/2001-July/071567.html

        3
  •  15
  •   Mark Rushakoff    15 年前

    其他人都已经提到了政治公众人物,但也要注意 在关键代码的中间有import语句。至少在python 2.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  
    
        4
  •  11
  •   Peter Mortensen mkoryak    12 年前

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

    否则,听从亚历克斯·马泰利的建议是明智的吗?

        5
  •  8
  •   jkp    15 年前

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

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

    def detect(self):
        import foobar
    

    如果工作正常,工具可用。然后在同一个模块中 foobar 可能需要模块,因此您必须在功能级别范围内再次导入它。显然,如果它是在模块级别导入的,那么事情将完全崩溃。

        6
  •  7
  •   Frozenskys    15 年前

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

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

    从这里: http://docs.python.org/tutorial/modules.html

        7
  •  6
  •   jcdyer Anand S Kumar    15 年前

    95%的情况下,您应该将所有导入的内容放在文件的顶部。您可能希望执行函数本地导入的一种情况是,为了避免循环导入,必须执行该操作。假设foo.py导入bar.py,bar.py中的函数需要从foo.py导入一些内容。如果将所有导入放在顶部,则导入依赖尚未编译的信息的文件时可能会遇到意外问题。在这种情况下,使用函数local import可以使代码在导入另一个模块时延迟,直到该模块的代码完全编译完毕,然后调用相关的函数。

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

    首先,而不是

    from prerequisite import foo
    

    直接导入先决条件,稍后将其称为prerequisite.foo。增加的冗长性通过增加代码透明度来回报自己。

    或者,(或者结合上面的内容)如果你的输入和它被使用的地方之间真的有这么长的距离,可能是你的模块太大了。需要一个其他任何东西都不使用的导入,这可能表明您的代码可以重构成一个更易于管理的块。

        8
  •  2
  •   Brian R. Bondy    15 年前

    PEP8 :

    进口总是放在 文件,在任何模块之后 注释和文档字符串,以及模块全局和常量之前。

    嘲笑进口并不是坏习惯。这样,导入只适用于您在其中使用它的函数。

    不过,如果导入的代码在块的顶部分组在一起,或者您希望它在文件的顶部全局,那么代码的可读性会更高。

        9
  •  2
  •   jab    15 年前

    好吧,我认为在文件开始时将所有导入分组是一个好的实践,因为每个人都知道在哪里查找是否希望知道加载了哪些libs