Python 中的好或坏实践:在文件中间导入
假设我有一个相对较长的模块,但只需要一次外部模块或方法。
在模块中间导入该方法或模块是否被认为可以?
或者导入应该仅位于模块的第一部分。
示例:
import string, pythis, pythat
...
...
...
...
def func():
blah
blah
blah
from pysomething import foo
foo()
etc
etc
etc
...
...
...
请证明您的答案并添加指向 PEP 的链接或相关来源
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
PEP 8 权威地指出:
PEP 8 应该是任何“内部”风格指南的基础,因为它总结了核心 Python 团队发现的最有效的总体风格(当然,与任何其他语言一样,也存在个人异议,但共识并且 BDFL 同意 PEP 8)。
PEP 8 authoritatively states:
PEP 8 should be the basis of any "in-house" style guide, since it summarizes what the core Python team has found to be the most effective style, overall (and with individual dissent of course, as on any other language, but consensus and the BDFL agree on PEP 8).
2001 年,Python 邮件列表上对此主题进行了详细讨论:
https://mail.python.org/pipermail/python-list/2001-July/071567.html
以下是该线程中讨论的一些原因。 Peter Hansen 指出,以下是不将导入全部放在文件顶部的三个原因:
范罗森(van Rossum)插话了第四个:
提供第五种是因为本地进口是避免循环进口问题的一种方式。
请随意阅读该主题以进行完整的讨论。
There was a detailed discussion of this topic on the Python mailing list in 2001:
https://mail.python.org/pipermail/python-list/2001-July/071567.html
Here are some of the reasons discussed in that thread. From Peter Hansen, here are three reasons not to have imports all at the top of the file:
Just van Rossum chimed in with a fourth:
A fifth was offered as local imports are a way to avoid the problem of circular imports.
Feel free to read through that thread for the full discussion.
其他人都已经提到了 PEP,但也要注意关键代码中间不要有 import 语句。 至少在Python 2.6下,当函数有import语句时,还需要多条字节码指令。
Everyone else has already mentioned the PEPs, but also take care to not have import statements in the middle of critical code. At least under Python 2.6, there are several more bytecode instructions required when a function has an import statement.
如果导入的模块不经常使用且导入成本较高,那么中间导入就可以。
否则,遵循 Alex Martelli 的建议是否明智。
If the imported module is infrequently used and the import is expensive, the in-the-middle-import is OK.
Otherwise, is it wise to follow Alex Martelli's suggestion.
这通常被认为是不好的做法,但有时这是不可避免的(比如当你必须避免循环导入时)。
必要时的一个例子:我使用 Waf 来构建我们所有的代码。 该系统分为多个工具,每个工具都在其自己的模块中实现。 每个工具模块都可以实现一个 detector() 方法来检测先决条件是否存在。 其中之一的示例可能会执行以下操作:
如果工作正常,则该工具可用。 然后,稍后在同一模块中可能需要 foobar 模块,因此您必须在函数级别范围内再次导入它。 显然,如果它是在模块级别导入的,事情就会完全崩溃。
It's generally considered bad practice, but sometimes it's unavoidable (say when you have to avoid a circular import).
An example of a time when it is necessary: I use Waf to build all our code. The system is split into tools, and each tool is implemented in it's own module. Each tool module can implent a
detect()
method to detect if the pre-requisites are present. An example of one of these may do the following:If this works correctly, the tool is usable. Then later in the same module the
foobar
module may be needed, so you would have to import it again, at function level scope. Clearly if it was imported at module level things would blow up completely.95% 的情况下,您应该将所有导入内容放在文件顶部。 您可能想要执行函数本地导入的一种情况是,如果您必须这样做以避免循环导入。 假设 foo.py 导入 bar.py,并且 bar.py 中的函数需要从 foo.py 导入某些内容。 如果将所有导入放在顶部,则导入依赖于尚未编译的信息的文件时可能会出现意外问题。 在这种情况下,具有函数本地导入可以让您的代码推迟导入其他模块,直到其代码完全编译并且您调用相关函数为止。
然而,看起来您的用例更多的是为了弄清楚 foo() 来自哪里。 在这种情况下,我更喜欢以下两件事之一:
首先,而不是
直接导入先决条件,然后将其称为先决条件.foo。 增加的冗长性通过提高代码透明度而得到了回报。
或者,(或结合上述情况)如果您的导入和使用它的地方之间的距离确实很远,则可能是您的模块太大。 需要一个没有其他东西使用的导入可能表明您的代码可以重构为更易于管理的块。
95% of the time, you should put all your imports at the top of the file. One case where you might want to do a function-local import is if you have to do it in order to avoid circular imports. Say foo.py imports bar.py, and a function in bar.py needs to import something from foo.py. If you put all your imports at the top, you could have unexpected problems importing files that rely on information that hasn't been compiled yet. In this case, having a function local import can allow your code to hold off on importing the other module until its code has been fully compiled, and you call the relevant function.
However, it looks like your use-case is more about making it clear where foo() is coming from. In this case, I would far prefer one of two things:
First, rather than
import prerequisite directly, and later on refer to it as prerequisite.foo. The added verbosity pays itself back in spades through increased code transparency.
Alternatively, (or in conjunction with the above) if it's really such a long distance between your import and the place it's being used, it may be that your module is too big. The need for an import that nothing else uses might be an indication of a place where your code could stand to be refactored into a more manageably-sized chunk.
在文件开头将所有导入分组在一起被认为是“良好的形式”。
从这里: http://docs.python.org/tutorial/modules.html
It is considered "Good Form" to group all imports together at the start of the file.
From here: http://docs.python.org/tutorial/modules.html
好吧,我认为在文件开头将所有导入分组在一起是一个很好的做法,因为如果想知道加载了哪些库,每个人都知道去哪里查找
Well, I think it is a good practice to group all imports together at start of file since everyone knows where to look if want to know which libs are loaded
PEP8:
限制导入并不是一个坏习惯。 因此,导入仅适用于您使用它的函数。
我认为,如果导入在块的顶部分组在一起,或者如果您希望它全局地位于文件的顶部,则代码会更具可读性。
PEP8:
It is not bad practice to have scopped imports. So that the import applies only to the function you used it in.
I think the code would be more readable though if the imports where grouped together at the top of the block or if you want it globally at the top of the file.