Python(和Django)最佳导入实践
在导入代码的各种方法中,有哪些方法比其他方法更适合使用?简而言之,这是一个链接 声明Python(和Django)最佳导入实践,python,django,python-import,Python,Django,Python Import,在导入代码的各种方法中,有哪些方法比其他方法更适合使用?简而言之,这是一个链接 声明 from foo.bar import MyClass 在正常情况下或者除非您知道自己在做什么,否则不是导入MyClass的首选方法。(相反,更好的方法是: import foo.bar as foobaralias 然后在代码中,访问MyClass使用 foobaralias.MyClass ) 简言之,上面引用的链接似乎表示,通常最好从模块导入所有内容,而不仅仅是模块的一部分 然而,我链接的那篇文章真
from foo.bar import MyClass
在正常情况下或者除非您知道自己在做什么,否则不是导入MyClass的首选方法。(相反,更好的方法是:
import foo.bar as foobaralias
然后在代码中,访问MyClass使用
foobaralias.MyClass
)
简言之,上面引用的链接似乎表示,通常最好从模块导入所有内容,而不仅仅是模块的一部分
然而,我链接的那篇文章真的很老了
我还听说,至少在Django项目的上下文中,最好只导入您想要使用的类,而不是整个模块。据说,这种形式有助于避免循环导入错误,或者至少使django导入系统不那么脆弱。有人指出,Django自己的代码似乎更喜欢“从x导入y”而不是“导入x”
假设我正在处理的项目没有使用
\uuuu init\uuuuu.py
的任何特殊功能。。。(我们所有的\uuuu init\uuuuu.py
文件都是空的),我应该选择什么导入方法,为什么?后者的优点是MyClass的起源更明确。前者将MyClass放在当前名称空间中,因此代码只能使用MyClass。因此,对于阅读定义MyClass的代码的人来说,这一点就不那么明显了。首先,也是导入的主要规则:永远不要使用来自foo导入的*
这篇文章讨论的是周期性导入的问题,这种问题今天仍然存在于结构不良的代码中。我不喜欢周期性进口;他们的出现是一个强烈的信号,表明某些模块做得太多,需要拆分。如果出于任何原因,您需要使用无法重新安排的周期性导入代码,import foo
是唯一的选项
在大多数情况下,import foo
和from foo import MyClass
之间没有太大区别。我更喜欢第二种,因为它所涉及的打字较少,但我可能会使用第一种方法有几个原因:
- 模块和类/值具有不同的名称。当导入值的名称与模块无关时,读者可能很难记住特定导入的来源
- 好:
将myapp.utils导入为utils;utils.frobnite()
- 好:
将myapp.utils导入为U;U.Frobnite()
- 错误:
来自myapp.utils导入Frobnate
- 好:
- 您正在从一个模块导入大量值。保存你的手指和读者的眼睛
- 坏:
从myapp.utils导入Frobnite、foo、bar、baz、MyClass、SomeOtherClass、#yada-yada
- 坏:
- 对我来说,这取决于具体情况。如果它是一个唯一命名的方法/类(即,不是
process()
或类似的东西),并且您将经常使用它,那么保存键入,只需从foo import MyClass执行
如果要从一个模块导入多个内容,最好只导入模块,然后执行module.bar、module.foo、module.baz
等操作,以保持名称空间干净
你还说
据说,这种形式有助于避免循环导入错误,或者至少使django导入系统不那么脆弱。有人指出,Django自己的代码似乎更喜欢“从x导入y”而不是“导入x”
我不认为这样或那样有助于防止循环进口。原因是,即使从x导入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
因此,test.py中的所有内容都是运行的,即使您只导入了b
,但Django中可能存在一个特殊的例外,您在Django中导入了一个实现模型(表示数据库表)的类。在这种情况下,最好说“from django.contrib.auth import User”。但正如我所说,这是特定于特定环境的约定;utils.frobnite()
?Joschua:那也没关系,因为任何人通读都可以看到从哪里导入frobnite
。