Python导入有什么好的经验法则?
我可以用Python导入模块的方式有点困惑。
import X import X as Y from A import B
我一直在阅读范围和命名空间,但是我想就什么是最好的策略,在哪种情况下以及为什么,提供一些实用的build议。 应该导入模块级别还是方法/function级别? 在__init__.py
还是在模块代码本身?
我的问题并没有真正回答“ Python包 – 按类导入,而不是文件 ”,但它显然是相关的。
在我们公司的生产代码中,我们试图遵循以下规则。
我们把导入放在文件的开头,紧跟在主文件的docstring之后,例如:
""" Registry related functionality. """ import wx # ...
现在,如果我们在导入的模块中导入一个less数几个的类,我们直接导入这个名字,这样在代码中我们只需要使用最后一个部分,例如:
from RegistryController import RegistryController from ui.windows.lists import ListCtrl, DynamicListCtrl
但是,有些模块包含几十个类,例如所有可能的例外列表。 然后我们导入模块本身并在代码中引用它:
from main.core import Exceptions # ... raise Exceptions.FileNotFound()
我们尽可能less地使用import X as Y
,因为它使search特定模块或类的使用变得困难。 但是,有时候,如果你想导入两个同名的类,但是存在于不同的模块中,你必须使用它,例如:
from Queue import Queue from main.core.MessageQueue import Queue as MessageQueue
作为一般规则,我们不在方法内部进行导入 – 它们只是使代码更慢,更不可读。 有些人可能会发现这是一个很好的方法来轻松解决循环导入问题,但更好的解决scheme是代码重组。
让我只在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
我通常会在模块级使用import X
如果您只需要一个模块中的单个对象,请使用from X import Y
只有使用import X as Y
,否则你会遇到名称冲突。
我只使用function级别的导入来导入我需要的东西,当模块被用作主要模块,如:
def main(): import sys if len(sys.argv) > 1: pass
HTH
上面有人说
from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
相当于
import X
import X
允许直接修改AP,而from X import ...
创buildAP的副本。 对于from X import A..P
,如果它们被修改,则不会获得variables的更新。 如果你修改它们,你只修改你的副本,但是X确实知道你的修改。
如果AP是function,你不会知道区别。
其他人已经覆盖了大部分的基础,但是我只想添加一个例子,当我尝试使用新版本的类或模块时,我将使用import X as Y
(临时)。
因此,如果我们正在迁移到一个新的模块实现,但不想一次削减代码库,我们可能会编写一个xyz_new
模块,并在我们已经迁移的源文件中执行此操作:
import xyz_new as xyz
然后,一旦我们切换了整个代码库,我们只需用xyz_new
replacexyz
模块,并将所有的导入改回
import xyz
不要这样做:
from X import *
除非你完全确定你会使用该模块中的每一件事情。 即使如此,你也许应该重新考虑使用不同的方法。
除此之外,这只是一个风格问题。
from X import Y
很好,可以节省你很多打字的时间。 我倾向于在相当频繁地使用某些东西的时候使用它但是如果你从这个模块中导入了很多东西,那么你最终可能会看到如下所示的导入语句:
from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
你明白了。 那是什么时候import的
import X
变得有用。 要么这样,要么我不是经常在X中使用任何东西。
我通常尝试使用常规import modulename
模块名称,除非模块名称很长或经常使用..
例如,我会做..
from BeautifulSoup import BeautifulStoneSoup as BSS
..so我可以做soup = BSS(html)
而不是BeautifulSoup.BeautifulStoneSoup(html)
要么..
from xmpp import XmppClientBase
..当我只使用XmppClientBase的时候,不要导入整个xmpp
如果要导入非常长的方法名称,或者防止对现有的import / variable / class /方法进行破坏(应该尽量避免完全避免,但并非总是可行),那么使用import x as y
会很方便。
说我想从另一个脚本运行一个main()函数,但我已经有一个main()函数..
from my_other_module import main as other_module_main
..不能用my_other_module的main
来代替我的main
函数
哦,有一件事 – 不要from x import *
– 它使你的代码很难理解,因为你不能容易地看到方法来自哪里( from x import *; from y import *; my_func()
– 哪里是my_func定义了吗?)
在所有情况下,你可以只import modulename
,然后做modulename.subthing1.subthing2.method("test")
…
from x import y as z
东西纯粹是为了方便 – 只要它使您的代码更易于阅读或写入,就可以使用它!
当你有一个写得很好的库时,有时候这个库是python的,你应该直接导入并使用它。 写得好的图书馆倾向于采取自己的生活和语言,导致愉快的阅读代码,你很less参考图书馆。 当一个图书馆写得很好,你不应该需要重命名或其他任何经常。
import gat node = gat.Node() child = node.children()
有时候不可能用这种方式来写,或者你想从你导入的库中提取东西。
from gat import Node, SubNode node = Node() child = SubNode(node)
有时候,如果你的导入string溢出了80列,你可以做很多事情,最好这样做:
from gat import ( Node, SubNode, TopNode, SuperNode, CoolNode, PowerNode, UpNode )
最好的策略是保持所有这些导入文件的顶部。 按照字母顺序sorting,首先导入expression式,然后从导入表格中导入。
现在我告诉你为什么这是最好的约定。
Python可以完全自动导入,当从全局名称空间中找不到时,它会从主导入中查找值。 但是这不是一个好主意。 我马上解释为什么。 除了实现比简单的导入更复杂外,程序员不会考虑依赖关系,而是从import产品的位置查找import产品,而不是仅仅关注import产品。
需要找出依赖是人们讨厌“从…import*”的一个原因。 尽pipe存在一些你需要这样做的不好的例子,例如opengl -wrappings。
所以导入定义对于定义程序的依赖性是非常有价值的。 这是你应该如何利用它们的方式。 从他们你可以快速检查一些奇怪的function从哪里import。
如果您有相同模块/类的不同实现,那么将import X as Y
很有用。
有了一些嵌套的try..import..except ImportError..import
可以隐藏你的代码的实现。 请参阅lxml etree导入示例 :
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")
我与杰森在不使用的事实
from X import *
但在我的情况下(我不是一个专家程序员,所以我的代码不符合编码风格太好)我通常在我的程序中包含所有的常量,如程序版本,作者,错误信息和所有的东西,所以文件只是定义,然后我进行导入
from const import *
这节省了我很多时间。 但它是唯一具有该导入的文件,这是因为该文件内的所有文件都只是variables声明。
在具有类和定义的文件中进行这种导入可能是有用的,但是当您必须阅读该代码时,您会花费大量时间来查找函数和类。