Python(以及Django)最佳导入实践

21

在许多导入代码的方式中,是否有一些方式比其他方式更可取?这个链接http://effbot.org/zone/import-confusion.htm简要说明:

from foo.bar import MyClass

在正常情况下或者你不知道自己在做什么的情况下,import MyClass 不是首选的导入方式。相反,更好的方式是:

import foo.bar as foobaralias

然后在代码中,要访问 MyClass,请使用

foobaralias.MyClass

简而言之,上面提到的链接说,通常最好从一个模块中导入所有内容而不是仅导入模块的部分内容。

然而,我引用的那篇文章实在太老了。

我也听说,在Django项目的情况下,最好仅导入你想要使用的类,而不是整个模块。有人说,这种方式有助于避免循环导入错误,或者至少使django的导入系统更加健壮。 有人指出,Django自己的代码似乎更喜欢“从x导入y”而不是“导入x”。

假设我们正在处理的项目没有使用__init__.py的特殊功能......(我们所有的__init__.py文件都是空的),那么我应该选择哪种导入方法,为什么?

3个回答

13

首先,最重要的导入规则是:绝对不能使用from foo import *

本文讨论的是循环导入问题,这在结构不良的代码中仍然存在。我不喜欢循环导入;它们的存在强烈暗示某个模块做了太多的事情,需要拆分。如果出于某种原因你需要使用无法重新排列的循环导入代码,则只能使用import foo

在大多数情况下,import foofrom foo import MyClass没有太大区别。我更喜欢后者,因为涉及的输入量较少,但以下原因可能是我使用前者的几个原因:

  • 模块和类/值具有不同的名称。当导入的值的名称与模块无关时,读者记住特定导入来自何处会很困难。

    • 好的:import myapp.utils as utils; utils.frobnicate()
    • 好的:import myapp.utils as U; U.frobnicate()
    • 不好的:from myapp.utils import frobnicate
  • 您从一个模块中导入了很多值。节省您的手指和读者的眼睛。

    • 不好的:from myapp.utils import frobnicate, foo, bar, baz, MyClass, SomeOtherClass, # yada yada

一个特定的例外可能出现在Django中,当你导入实现模型(代表数据库表)的类时。在这种情况下,最好说“from django.contrib.auth import User”。但正如我所说,这是特定环境下的惯例。 - Peter Rowell
2
那么 from myapp import utils; utils.frobnicate() 呢? - Joschua
1
Joschua:这也没关系,因为任何阅读代码的人都能看到frobnicate是从哪里导入的。 - John Millikin

6
对我而言,这取决于情况。如果是一个独特命名的方法/类(即不是"process()"或类似的名称),并且您要经常使用它,则为了缩短输入长度,请只执行 "from foo import MyClass"。
如果您从一个模块中导入多个内容,则最好仅导入该模块,并执行"module.bar, module.foo,module.baz"等操作,以保持命名空间的清晰。
你还说:
据说这种形式有助于避免循环导入错误,或至少使Django的导入系统不那么脆弱。有人指出,Django自己的代码似乎更喜欢“从x导入y”而不是“导入x”。
我没看出来这两种方法如何有助于防止循环导入。原因是,即使您执行“from x import y”,所有的"x"也会被导入。只有"y"会被带入当前命名空间,但整个模块"x"都会被处理。请尝试以下示例:在test.py中放入以下内容:
def a():
    print "a"

print "hi"

def b():
    print "b"

print "bye"

然后在 'runme.py' 文件中输入:

from test import b

b()

然后只需要执行 python runme.py

你将会看到以下输出:

hi
bye
b

即使您只导入了b,但是test.py中的所有内容都被运行。


2
后一种方式的优点在于MyClass的来源更加明确。前一种方式将MyClass放置在当前命名空间中,因此代码可以不带限定符地使用MyClass。因此,对于阅读代码的人来说,MyClass的定义位置不太明显。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接