提问人:Simon 提问时间:10/11/2008 最后编辑:CommunitySimon 更新时间:4/5/2015 访问量:53220
Python 导入的良好经验法则是什么?
What are good rules of thumb for Python imports?
问:
我对在 Python 中导入模块的多种方式感到有些困惑。
import X
import X as Y
from A import B
我一直在阅读有关范围和命名空间的信息,但我想要一些关于什么是最佳策略、在什么情况下以及为什么的实用建议。导入应该在模块级别还是方法/函数级别进行?在模块代码本身中?__init__.py
“Python 包 - 按类导入,而不是文件”并没有真正回答我的问题,尽管它显然是相关的。
答:
我通常会在模块级别使用。如果只需要模块中的单个对象,请使用 。import X
from X import Y
仅在您遇到名称冲突时使用。import X as Y
当模块用作主模块时,我只在函数级别使用导入来导入我需要的东西,例如:
def main():
import sys
if len(sys.argv) > 1:
pass
HTH型
在我们公司的生产代码中,我们尽量遵循以下规则。
我们将导入放在文件的开头,紧跟在主文件的文档字符串之后,例如:
"""
Registry related functionality.
"""
import wx
# ...
现在,如果我们导入的类是导入模块中为数不多的类之一,我们直接导入名称,因此在代码中我们只需要使用最后一部分,例如:
from RegistryController import RegistryController
from ui.windows.lists import ListCtrl, DynamicListCtrl
但是,有些模块包含数十个类,例如所有可能的异常列表。然后我们导入模块本身并在代码中引用它:
from main.core import Exceptions
# ...
raise Exceptions.FileNotFound()
我们尽可能少地使用 ,因为它使搜索特定模块或类的用法变得困难。但是,有时,如果您希望导入两个具有相同名称但存在于不同模块中的类,则必须使用它,例如:import X as Y
from Queue import Queue
from main.core.MessageQueue import Queue as MessageQueue
作为一般规则,我们不会在方法内部进行导入——它们只会使代码变慢且可读性降低。有些人可能会发现这是轻松解决循环导入问题的好方法,但更好的解决方案是代码重组。
评论
如果您对同一模块/类有不同的实现,则该功能很有用。import X as Y
使用一些嵌套的 s,您可以在代码中隐藏实现。请参阅 lxml etree 导入示例:try..import..except ImportError..import
try:
from lxml import etree
print("running with lxml.etree")
except ImportError:
try:
# Python 2.5
import xml.etree.cElementTree as etree
print("running with cElementTree on Python 2.5+")
except ImportError:
try:
# Python 2.5
import xml.etree.ElementTree as etree
print("running with ElementTree on Python 2.5+")
except ImportError:
try:
# normal cElementTree install
import cElementTree as etree
print("running with cElementTree")
except ImportError:
try:
# normal ElementTree install
import elementtree.ElementTree as etree
print("running with ElementTree")
except ImportError:
print("Failed to import ElementTree from any known place")
我一般尽量使用常规的,除非模块名称很长,或者经常使用。import modulename
例如,我会做..
from BeautifulSoup import BeautifulStoneSoup as BSS
..所以我可以代替soup = BSS(html)
BeautifulSoup.BeautifulStoneSoup(html)
或。。
from xmpp import XmppClientBase
..而不是在我只使用 XmppClientBase 时导入整个 xmpp
如果您想导入很长的方法名称,或者防止破坏现有的导入/变量/类/方法(您应该尝试完全避免这种情况,但并不总是可行的),使用非常方便import x as y
假设我想从另一个脚本运行一个 main() 函数,但我已经有一个 main() 函数。
from my_other_module import main as other_module_main
..不会用my_other_module的函数替换我的函数main
main
哦,有一件事 - 不要做 - 它使你的代码很难理解,因为你不容易看到方法来自哪里( - my_func在哪里定义?from x import *
from x import *; from y import *; my_func()
在所有情况下,你都可以做,然后做......import modulename
modulename.subthing1.subthing2.method("test")
这些东西纯粹是为了方便 - 只要它能使你的代码更容易阅读或编写,就使用它!from x import y as z
评论
xmpp
XmppClientBase
as
BSS()
from
from mymod import MyClass
class MyOtherClass(MyClass):
其他人已经涵盖了这里的大部分内容,但我只想添加一个案例,当我尝试一个类或模块的新版本时,我将(暂时)使用。import X as Y
因此,如果我们要迁移到模块的新实现,但不想一次切断所有代码库,我们可能会编写一个模块并在我们迁移的源文件中执行此操作:xyz_new
import xyz_new as xyz
然后,一旦我们切入整个代码库,我们只需将模块替换为并将所有导入更改回xyz
xyz_new
import xyz
别这样:
from X import *
除非你绝对确定你会使用该模块中的每一个东西。即便如此,您可能也应该重新考虑使用不同的方法。
除此之外,这只是一个风格问题。
from X import Y
很好,可以为您节省大量打字时间。当我经常使用它时,我倾向于使用它,但是如果您从该模块导入大量内容,则最终可能会得到如下所示的 import 语句:
from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
你明白了。那时进口喜欢
import X
变得有用。要么是这样,要么是我并没有经常在 X 中使用任何东西。
评论
让我在 Guido van Rossum 发起的 django-dev 邮件列表上粘贴一段对话:
[...] 例如,它是 Google Python 风格指南[1] 的一部分,所有 导入必须导入模块,而不是从中导入类或函数 模块。类和函数的数量比实际数量多得多 模块,所以回忆一个特定的东西来自哪里是很重要的 如果它以模块名称为前缀,则更容易。通常有多个模块 碰巧用相同的名称定义事物 -- 所以代码的读者 不必返回文件顶部即可查看从哪个 导入给定名称的模块。
来源: http://groups.google.com/group/django-developers/browse_thread/thread/78975372cdfb7d1a
1:http://code.google.com/p/soc/wiki/PythonStyleGuide#Module_and_package_imports
评论
当你有一个写得很好的库时,这在 python 中有时是这种情况,你应该导入它并使用它。写得好的库往往会有自己的生命和语言,从而产生令人愉悦的代码,而你很少引用库。当一个库写得很好时,你不应该经常需要重命名或其他任何事情。
import gat
node = gat.Node()
child = node.children()
有时不可能以这种方式编写它,或者你想从你导入的库中取出东西。
from gat import Node, SubNode
node = Node()
child = SubNode(node)
有时你会为很多事情这样做,如果你的导入字符串溢出了 80 列,这样做是个好主意:
from gat import (
Node, SubNode, TopNode, SuperNode, CoolNode,
PowerNode, UpNode
)
最好的策略是将所有这些导入保留在文件的顶部。最好按字母顺序排序,首先是 import -statements,然后是 from import -statements。
现在我告诉你为什么这是最好的约定。
Python 完全可以有一个自动导入,当无法从全局命名空间中找到该值时,它会从主导入中查找该值。但这不是一个好主意。我简要解释一下原因。除了实现它比简单的导入更复杂之外,程序员不会过多地考虑问题,并找出从哪里导入的东西应该以其他方式完成,而不仅仅是查看导入。
需要找出缺陷是人们讨厌“来自......导入 *”。不过,存在一些需要执行此操作的坏例子,例如 opengl -wrappings。
因此,导入定义实际上很有价值,因为它定义了程序的缺点。这是您应该如何利用它们的方式。从中,您可以快速检查从哪里导入一些奇怪的函数。
我和杰森在一起,因为没有使用
from X import *
但就我而言(我不是专业的程序员,所以我的代码不太符合编码风格)我通常会在我的程序中做一个包含所有常量的文件,如程序版本、作者、错误消息和所有这些东西,所以文件只是定义,然后我进行导入
from const import *
这为我节省了很多时间。但它是唯一具有该导入的文件,这是因为该文件中的所有文件都只是变量声明。
在具有类和定义的文件中执行这种导入可能很有用,但是当您必须读取该代码时,您将花费大量时间来查找函数和类。
上面有人说
from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
相当于
import X
import X
允许直接修改 A-P,同时创建 A-P 的副本。因为如果变量被修改,则不会获得变量的更新。如果你修改它们,你只修改你的副本,但 X 确实知道你的修改。from X import ...
from X import A..P
如果 A-P 是函数,您将不知道其中的区别。
评论
mock
X.A
import X
评论