Python(和Django)最佳导入实践
在导入代码的各种方式中,有没有一些方式比其他方式更好呢?这个链接 http://effbot.org/zone/import-confusion.htm 简单地说,
from foo.bar import MyClass
在正常情况下,或者除非你知道自己在做什么,不推荐用这种方式来导入 MyClass。更好的方式应该是:
import foo.bar as foobaralias
然后在代码中,要使用 MyClass 时可以这样:
foobaralias.MyClass
总的来说,上面提到的链接似乎在说,通常来说,从一个模块中导入所有内容比只导入模块的一部分要好。
不过,我提到的那篇文章其实很旧了。
我还听说,在 Django 项目的上下文中,最好只导入你想用的类,而不是整个模块。有人说这种方式可以避免循环导入错误,或者至少让 Django 的导入系统不那么脆弱。有人指出,Django 自己的代码似乎更喜欢用 "from x import y" 而不是 "import x"。
假设我正在做的项目没有使用 __init__.py
的任何特殊功能……(我们所有的 __init__.py
文件都是空的),那么我应该偏向使用哪种导入方法,为什么呢?
3 个回答
后者的好处在于,MyClass 的来源更加明确。前者把 MyClass 放在当前的命名空间里,这样代码就可以直接使用 MyClass,而不需要加上其他的前缀。所以,对于阅读代码的人来说,MyClass 的定义位置就不那么明显了。
首先,关于导入的一个重要规则:绝对不要使用 from foo import *
。
这篇文章在讨论循环导入的问题,这在结构不好的代码中仍然存在。我不喜欢循环导入;它的出现通常意味着某个模块的功能过于复杂,需要拆分。如果因为某种原因你必须处理包含循环导入的代码,而这些代码又无法重新安排,那么 import foo
是唯一的选择。
在大多数情况下,import foo
和 from 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
- 不好的例子:
对我来说,这要看具体情况。如果你要用的方法或类名字很特别(比如,不是像 process()
这种常见名字),而且你会用得非常频繁,那就省省打字,直接用 from foo import MyClass
吧。
如果你要从一个模块里导入很多东西,可能更好的是直接导入整个模块,然后用 module.bar, module.foo, module.baz
这样的方式,这样可以保持命名空间的整洁。
你还提到过
有人说这种方式可以帮助避免循环导入错误,或者至少让 Django 的导入系统不那么脆弱。有人指出,Django 自己的代码似乎更喜欢用 "from x import y" 而不是 "import 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 里的所有内容还是被执行了。