cod*_*ape 112 python conventions
PEP 8说:
- 导入总是放在文件的顶部,就在任何模块注释和文档字符串之后,以及模块全局变量和常量之前.
在发生时,我违反了PEP 8.有时我会在函数中导入内容.作为一般规则,如果导入仅在单个函数中使用,则执行此操作.
任何意见?
编辑(我觉得导入函数的原因可能是一个好主意):
主要原因:它可以使代码更清晰.
from m import xxx.看到m.xxx这个功能可能会告诉我更多.具体取决于m:它是一个众所周知的顶级模块/包(import m)吗?或者它是一个子模块/包(from a.b.c import m)?小智 77
从长远来看,我认为你会很高兴你的大部分导入都位于文件顶部,这样你就可以一目了然地看出你的模块需要导入的复杂程度.
如果我将新代码添加到现有文件中,我通常会在需要的地方进行导入,然后如果代码保持不变,我会通过将导入行移动到文件顶部来使事情变得更加永久.
另外一点,我更喜欢ImportError在运行任何代码之前获得异常 - 作为完整性检查,这是在顶部导入的另一个原因.
我pyChecker用来检查未使用的模块.
Ric*_*and 42
在这方面,我有两次违反PEP 8:
import pdb; pdb.set_trace()这很方便b/c我不想放在import pdb我可能要调试的每个模块的顶部,并且当我删除断点时很容易记住删除导入.在这两种情况之外,将所有内容放在首位是个好主意.它使依赖关系更加清晰.
S.L*_*ott 19
以下是我们使用的四个导入用例
import(和from x import y和import x as y)在顶部
选择进口.在顶部.
import settings
if setting.something:
import this as foo
else:
import that as foo
Run Code Online (Sandbox Code Playgroud)有条件导入.与JSON,XML库等一起使用.在顶部.
try:
import this as foo
except ImportError:
import that as foo
Run Code Online (Sandbox Code Playgroud)动态导入.到目前为止,我们只有一个例子.
import settings
module_stuff = {}
module= __import__( settings.some_module, module_stuff )
x = module_stuff['x']
Run Code Online (Sandbox Code Playgroud)
请注意,此动态导入不会引入代码,但会引入用Python编写的复杂数据结构.它有点像腌制的数据,除非我们手工腌制.
这也或多或少地位于模块的顶部
以下是我们如何使代码更清晰:
保持模块简短.
如果我在模块的顶部有我的所有导入,我必须去那里查看确定名称是什么.如果模块很短,那很容易做到.
在某些情况下,在使用名称的位置附近有额外信息可以使函数更容易理解.如果模块很短,那很容易做到.
要记住一件事:不必要的进口可能会导致性能问题.因此,如果这是一个经常调用的函数,那么最好只将导入放在顶部.当然这是一个优化,所以如果有一个有效的案例表明在函数内部导入比在文件顶部导入更清楚,那么在大多数情况下这会胜过性能.
如果你正在做IronPython,我被告知最好导入内部函数(因为在IronPython中编译代码可能很慢).因此,您可以通过导入内部函数来获得一种方法.但除此之外,我认为打击惯例是不值得的.
作为一般规则,如果导入仅在单个函数中使用,则执行此操作.
我想提出的另一点是,这可能是一个潜在的维护问题.如果添加使用以前仅由一个函数使用的模块的函数会发生什么?你会记得将导入添加到文件顶部吗?或者您要扫描每个功能进口?
FWIW,有些情况下导入函数内部是有意义的.例如,如果要在cx_Oracle中设置语言,则需要在导入之前设置NLS _LANG环境变量.因此,您可能会看到如下代码:
import os
oracle = None
def InitializeOracle(lang):
global oracle
os.environ['NLS_LANG'] = lang
import cx_Oracle
oracle = cx_Oracle
Run Code Online (Sandbox Code Playgroud)
对于自我测试的模块,我之前已经破坏了这个规则.也就是说,它们通常只用于支持,但是我为它们定义了一个main,这样如果你自己运行它们就可以测试它们的功能.在这种情况下,我有时会导入getopt并且cmd只是在main中,因为我希望有人能够清楚地看到这些模块与模块的正常操作无关,并且仅包含在测试中.
看看 sqlalchemy 中使用的替代方法:依赖注入:
@util.dependencies("sqlalchemy.orm.query")
def merge_result(query, *args):
#...
query.Query(...)
Run Code Online (Sandbox Code Playgroud)
请注意导入的库是如何在装饰器中声明的,并作为参数传递给函数!
这种方法使代码更加简洁,并且比语句运行速度快 4.5 倍import!
基准:https://gist.github.com/kolypto/589e84fbcfb6312532658df2fabdb796
还有另一种(可能是“角落”)情况,它可能对import内部很少使用的功能有益:缩短启动时间。
我曾经遇到过这个问题,在小型物联网服务器上运行一个相当复杂的程序,该程序从串行线路接受命令并执行操作,可能是非常复杂的操作。
将语句放在import文件顶部意味着在服务器启动之前处理所有导入;由于import列表包含jinja2、lxml和signxml其他“重量级”(SoC 不是很强大),这意味着在第一条指令实际执行之前的几分钟。
OTOH 将大多数导入放入函数中,我能够在几秒钟内让服务器在串行线上“活动”。当然,当实际需要模块时,我必须付出代价(注意:这也可以通过import在空闲时间生成一个执行 s 的后台任务来缓解)。