导入函数是pythonic吗?

PEP 8说:

  • 导入总是放在文件的顶部,在任何模块注释和文档string之后,在模块全局variables和常量之前。

在发生时,我违反了PEP 8.有时我在函数内部导入东西。 作为一般规则,如果有一个导入只在一个函数中使用,我会这样做。

有什么意见?

编辑(我觉得在function导入的原因可以是一个好主意):

主要原因:可以使代码更清晰。

  • 当看一个函数的代码时,我可能会问自己:“什么是函数/类xxx?” (xxx在函数内部使用)。 如果我把所有的input都放在模块的顶部,我必须去看那里确定xxx是什么。 from m import xxx使用时,这是更多的问题。 在函数中看到m.xxx可能会告诉我更多。 取决于m是什么:它是一个众所周知的顶级模块/包( import m )? 或者它是一个子模块/包( from abc import m )?
  • 在某些情况下,使用xxx附近的附加信息(“什么是xxx?”)可以使得该function更易于理解。

从长远来看,我认为你会感激你的大部分导入在文件的顶部,这样你可以一目了然地告诉你需要导入的模块有多复杂。

如果我将新代码添加到现有文件中,我通常会在需要的地方进行导入,然后如果代码保留,我会通过将导入线移动到文件顶部来使事情更加永久。

还有一点,我更喜欢在任何代码运行之前得到一个ImportErrorexception – 作为一个完整的检查,所以这是导入顶部的另一个原因。

我使用pyChecker来检查未使用的模块。

在这方面有两次我违反了PEP 8:

  • 循环导入:模块A导入模块B,但模块B中的东西需要模块A(尽pipe这通常是我需要重构模块以消除循环依赖的标志)
  • 插入一个pdb断点: import pdb; pdb.set_trace() import pdb; pdb.set_trace()这是方便的b / c我不想把import pdb放在每个模块的顶部,我可能想要debugging,并且很容易记住当我删除断点时删除导入。

除了这两种情况之外,把所有东西都放在最上面是个好主意。 它使依赖关系更清晰。

以下是我们使用的四个导入用例

  1. importfrom x import yimport x as y )在顶部

  2. select导入。 在顶部。

     import settings if setting.something: import this as foo else: import that as foo 
  3. 有条件的导入。 与JSON,XML库等一起使用。 在顶部。

     try: import this as foo except ImportError: import that as foo 
  4. dynamic导入。 到目前为止,我们只有一个例子。

     import settings module_stuff = {} module= __import__( settings.some_module, module_stuff ) x = module_stuff['x'] 

    请注意,这种dynamic导入不会引入代码,但会带来用Python编写的复杂数据结构。 除了我们用手腌制之外,它有点像一个腌制的数据。

    这也是,或多或less,在一个模块的顶部


以下是我们所做的使代码更清晰:

  • 保持模块简短。

  • 如果我把所有的input都放在模块的顶部,我必须去那里看看是什么名字。 如果模块很短,那很容易做到。

  • 在某些情况下,使用名称附近的额外信息可以使该function更易于理解。 如果模块很短,那很容易做到。

有一件事要记住:不必要的import可能会导致性能问题。 所以如果这是一个会频繁调用的函数,那么最好把导入放在最前面。 当然这一个优化,所以如果有一个有效的例子来说明,在函数内部导入比在文件顶部导入更清晰,那么在大多数情况下,性能是胜于性能的。

如果你在做IronPython,我被告知最好导入里面的函数(因为在IronPython中编译代码可能会很慢)。 因此,您可能可以通过导入内部函数来获得方法。 但除此之外,我认为这是不值得与常规打交道的。

作为一般规则,如果有一个导入只在一个函数中使用,我会这样做。

另一点我想说的是,这可能是一个潜在的维护问题。 如果添加一个使用之前仅由一个函数使用的模块的函数,会发生什么情况? 你会记得将导入添加到文件的顶部? 还是你要扫描每一个importfunction?

FWIW,有些情况下在函数内部导入是有意义的。 例如,如果要在cx_Oracle中设置语言,则需要导入之前设置NLS _ LANG环境variables。 因此,你可能会看到这样的代码:

 import os oracle = None def InitializeOracle(lang): global oracle os.environ['NLS_LANG'] = lang import cx_Oracle oracle = cx_Oracle 

我已经打破了这个规则自我testing的模块。 也就是说,它们通常只是用于支持,但是我为它们定义了一个main,所以如果你自己运行它们,你可以testing它们的function。 在这种情况下,我有时会将getoptcmd导入到main中,因为我希望读取代码的人清楚,这些模块与模块的正常运行无关,只是包含在testing中。

只要它是import而不是from x import * ,你应该把它们放在最前面。 它只在全局名称空间中添加一个名称,并且坚持使用PEP 8.另外,如果以后需要它,则不必移动任何东西。

这没什么大不了的,但是因为几乎没有什么区别,所以我build议按照PEP 8的说法做。

来自两次加载模块的问题 – 为什么不是两个?

脚本顶部的导入将指示依赖关系,而函数中的另一个导入使得此函数更加primefaces化,而看起来不会导致任何性能劣势,因为连续导入是便宜的。