fly*_*ire 58 python python-import
假设我有一个相对较长的模块,但只需要一次外部模块或方法.
在模块中间导入该方法或模块是否可以?
或者应该import只在模块的第一部分.
例:
import string, pythis, pythat
...
...
...
...
def func():
blah
blah
blah
from pysomething import foo
foo()
etc
etc
etc
...
...
...
Run Code Online (Sandbox Code Playgroud)
请证明您的答案是合理的,并添加指向PEP或相关来源的链接
Ale*_*lli 63
PEP 8权威地指出:
导入总是放在文件的顶部,就在任何模块注释和文档字符串之后,以及模块全局变量和常量之前.
PEP 8应该是任何"内部"风格指南的基础,因为它总结了核心Python团队发现的最有效的风格,总体而言(当然,与个人异议一样,与任何其他语言一样,但是达成共识并且BDFL同意PEP 8).
ire*_*ses 18
2001年在Python邮件列表上对该主题进行了详细讨论:
https://mail.python.org/pipermail/python-list/2001-July/071567.html
Mar*_*off 17
其他人都已经提到了PEP,但也注意在关键代码中间没有 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
Run Code Online (Sandbox Code Playgroud)
这通常被认为是不好的做法,但有时它是不可避免的(比如当你必须避免循环导入时).
必要时的一个例子:我使用Waf来构建我们所有的代码.系统分为工具,每个工具都在自己的模块中实现.每个工具模块可以实现一种detect()方法来检测是否存在先决条件.其中一个示例可能会执行以下操作:
def detect(self):
import foobar
Run Code Online (Sandbox Code Playgroud)
如果这可以正常工作,该工具是可用的.然后在同一模块中foobar可能需要该模块,因此您必须在功能级别范围内再次导入它.显然,如果它是在模块级别导入的,那么事情会完全爆炸.
在文件开头将所有导入分组在一起被视为"良好格式".
模块可以导入其他模块.习惯但不要求将所有import语句放在模块的开头(或脚本,就此而言).导入的模块名称放在导入模块的全局符号表中.
从这里:http://docs.python.org/tutorial/modules.html
95%的情况下,您应该将所有导入放在文件的顶部.您可能希望执行函数本地导入的一种情况是,为了避免循环导入,必须执行此操作.假设foo.py导入bar.py,bar.py中的函数需要从foo.py导入一些东西.如果将所有导入放在顶部,则导入依赖于尚未编译的信息的文件时可能会出现意外问题.在这种情况下,具有本地导入功能可以允许代码在导入其他模块之前推迟其代码完全编译,并调用相关函数.
但是,看起来你的用例更多的是要明确foo()的来源.在这种情况下,我更喜欢以下两种情况之一:
首先,而不是
from prerequisite import foo
Run Code Online (Sandbox Code Playgroud)
直接导入先决条件,稍后将其称为prerequisite.foo.增加的详细程度通过提高代码透明度在自己中得到了回报.
或者,(或与上述相结合)如果你的导入和它正在使用的地方之间真的有这么长的距离,那么你的模块可能太大了.没有其他任何用途的导入需求可能表明您的代码可以被重构为更易管理的块.