“导入模块”或“从模块导入”

我试图find一个关于是最好使用import module还是from module import的综合指南。 我刚刚开始使用Python,打算用Django开发Web应用程序,我试着从头开始学习最佳实践。

基本上,我希望如果有人能分享他们的经验,其他开发者有什么样的偏好,以及什么是避免任何问题的最好方法。

import modulefrom module import foo的区别主要是主观的。 select一个你最喜欢的,并保持一致的使用它。 这里有几点可以帮助你决定。

import module

  • 优点:
    • 减less维护您的import报表。 不需要添加任何额外的导入来开始使用模块中的其他项目
  • 缺点:
    • 在你的代码中inputmodule.foo可能是单调乏味的(冗长的,可以通过使用import module as mo来最小化,然后inputmo.foo

from module import foo

  • 优点:
    • 减less打字使用foo
    • 更多的控制模块的哪些项目可以被访问
  • 缺点:
    • 要使用模块中的新项目,您必须更新import语句
    • 你失去了关于foo上下文。 例如, ceil()math.ceil()相比,

这两种方法都是可以接受的,但不要使用from module import *

对于任何合理的大量代码,如果您import *您可能会将其固化到模块中,无法移除。 这是因为很难确定代码中使用哪些项目来自“模块”,这使得您很容易达到您认为不再使用import程度,但是难以确定。

这两种方式的支持是有原因的:有时候一种比另一种更合适。

  • import module :当你使用模块的许多位时很好。 缺点是您需要使用模块名称来限定每个引用。

  • from module import ... :很好,导入的项目可直接使用,无需模块名称前缀。 缺点是你必须列出你使用的每个东西,而且在代码中不清楚哪里来的东西。

要使用哪一个取决于哪个使得代码清晰可读,并且与个人偏好有很大关系。 我倾向于import module一般是因为在代码中非常清楚对象或函数来自哪里。 我使用from module import ...当我在代码中使用一些对象/函数。

这里还有另一个细节,没有提到,与写入模块有关。 当然,这可能不是很常见,但我不时需要它。

由于引用和名称绑定在Python中的工作方式,如果您想要更新模块中的某个符号(例如foo.bar),并从该模块外部获取其他导入代码“see”,则必须导入foo a某种方式。 例如:

模块foo:

 bar = "apples" 

模块一:

 import foo foo.bar = "oranges" # update bar inside foo module object 

模块b:

 import foo print foo.bar # if executed after a's "foo.bar" assignment, will print "oranges" 

但是,如果您导入符号名称而不是模块名称,这将不起作用。

例如,如果我在模块a中这样做:

 from foo import bar bar = "oranges" 

没有代码之外的代码将看到“桔子”栏,因为我的设置栏只影响模块a内的名称“栏”,它没有“伸手进去”foo模块对象并更新它的“栏”。

我个人总是使用

 from package.subpackage.subsubpackage import module 

然后访问一切

 module.function module.modulevar 

等等。原因是同时你有简短的调用,而且你清楚地定义了每个例程的模块名字空间,如果你必须在你的源代码中search一个给定模块的用法,这是非常有用的。

不用说,不要使用import *,因为它会污染你的命名空间,并且不会告诉你给定函数来自哪里(来自哪个模块)

当然,如果两个不同的包中的两个不同模块具有相同的模块名称,则可能会遇到麻烦

 from package1.subpackage import module from package2.subpackage import module 

在这种情况下,当然你遇到了麻烦,但是有一个强烈的暗示,你的包装布局是有缺陷的,你必须重新思考它。

已经有很多人解释过关于import ,甚至我想试着更深入的解释一下,所有的地方在哪里得到了改变:

首先让我解释一下:

导入X:

 imports the module X, and creates a reference to that module in the current namespace. Then you need to define completed module path to access a particular attribute or method from inside the module. 

例如:X.name或X.attribute

从X导入*:

 *imports the module X, and creates references to all public objects defined by that module in the current namespace (that is, everything that doesn't have a name starting with “_”) or what ever the name you mentioned. Or in other words, after you've run this statement, you can simply use a plain name to refer to things defined in module X. But X itself is not defined, so X.name doesn't work. And if name was already defined, it is replaced by the new version. And if name in X is changed to point to some other object, your module won't notice. * This makes all names from the module available in the local namespace. 

现在让我们看看我们什么时候import XY

 >>> import sys >>> import os.path 

使用名称osos.path检查sys.modules:

 >>> sys.modules['os'] <module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'> >>> sys.modules['os.path'] <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> 

使用名称osos.path检查globals()和locals()命名空间字典:

  >>> globals()['os'] <module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'> >>> locals()['os'] <module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'> >>> globals()['os.path'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'os.path' >>> 

从上面的例子中我们发现只有os被插入到本地和全局的命名空间中。 所以,我们应该可以使用:

  >>> os <module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'> >>> os.path <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> >>> 

但不是path

 >>> path Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'path' is not defined >>> 

一旦从locals()命名空间中删除了os ,即使存在于sys.modules中,也不能访问os以及os.path

 >>> del locals()['os'] >>> os Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'os' is not defined >>> os.path Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'os' is not defined >>> 

现在让我们来看看:

**来自:**

 >>> import sys >>> from os import path 

使用名称os和os.path检查sys.modules:

 >>> sys.modules['os'] <module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'> >>> sys.modules['os.path'] <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> 

哦,我们发现在sys.modules中,我们使用import namefind了和之前一样的东西

好的,让我们看看它在locals()和globals()命名空间字典中的样子:

 >>> globals()['path'] <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> >>> locals()['path'] <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> >>> globals()['os'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'os' >>> 

您可以通过使用名称path不通过os.path

 >>> path <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> >>> os.path Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'os' is not defined >>> 

让我们从locals()中删除'path':

 >>> del locals()['path'] >>> path Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'path' is not defined >>> 

最后一个例子使用别名:

 >>> from os import path as HELL_BOY >>> locals()['HELL_BOY'] <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> >>> globals()['HELL_BOY'] <module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> >>> 

没有定义path:

 >>> globals()['path'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'path' >>> 
 import module 

最好的时候,你会使用模块的许多function。

 from module import function 

最好是当你只需要function时候,要避免使用模块中的所有函数和types来污染全局命名空间。

这里还有另外一个不同的地方 这是从http://docs.python.org/2/tutorial/modules.html逐字复制的;

请注意,使用时

 from package import item 

该项可以是包的子模块(或子包),也可以是包中定义的其他名称,如函数,类或variables。 导入语句首先testing项目是否在包中定义; 如果没有,它假定它是一个模块,并尝试加载它。 如果找不到,则会引发ImportErrorexception。

相反,当使用像

 import item.subitem.subsubitem 

除了最后的每件商品都必须是一个包装; 最后一个项目可以是一个模块或一个包,但不能是前一个项目中定义的类或函数或variables。

为了增加人们from x import *所说的话:除了使得更难辨别名称来自哪里之外,这抛出了像Pylint这样的代码检查器。 他们会将这些名称报告为未定义的variables。

我自己的答案主要取决于第一,我将使用多less个不同的模块。 如果我只打算使用一个或两个,我会经常使用fromimport因为它在文件的其余部分减less击键,但如果我要使用许多不同的模块,我因为这意味着每个模块引用都是自我logging的,所以更喜欢import 。 我可以看到每个符号来自哪里,而不必四处打猎。

通常我更喜欢纯导入的自我logging风格,并且只有当我input模块名称的次数增加到10到20以上时,才更改为from。import,即使只导入了一个模块也是如此。

我刚刚发现了这两种方法之间更细微的差别。

如果模块foo使用以下导入:

 from itertools import count 

然后模块bar可以错误地使用count就像它是在foo中定义的,而不是在itertools

 import foo foo.count() 

如果foo使用:

 import itertools 

这个错误仍然是可能的,但不太可能。 bar需要:

 import foo foo.itertools.count() 

这给我造成了一些麻烦。 我有一个错误的模块,从一个没有定义它的模块导入exception,只从其他from module import SomeException (使用from module import SomeException )。 当不再需要和取消import时,违规模块被打破。

 import package import module 

通过import ,令牌必须是一个模块(一个包含Python命令的文件)或一个包(包含文件__init__.pysys.path中的一个文件夹)。

当有子包时:

 import package1.package2.package import package1.package2.module 

文件夹(包)或文件(模块)的要求是相同的,但文件夹或文件必须位于package2 ,必须位于package1 ,并且package1package2必须包含__init__.py文件。 https://docs.python.org/2/tutorial/modules.html

fromimport的风格:

 from package1.package2 import package from package1.package2 import module 

包或模块将包含import语句的文件的名称空间作为module (或package )而不是package1.package2.module 。 你总是可以绑定一个更方便的名字:

 a = big_package_name.subpackage.even_longer_subpackage_name.function 

只有fromimport的风格,你可以命名一个特定的function或variables:

 from package3.module import some_function 

是允许的,但是

 import package3.module.some_function 

不允许。

导入模块 – 您不需要额外的努力从模块中获取其他东西。 它有缺点,如多余的打字

模块导入 – 减lessinput和更多的控制模块的哪些项目可以访问。要使用模块中的新项目,您必须更新您的导入语句。

两个区别在这里:1.只有“from … import …”才能导入func / class / var符号名称; 2.只有当导入的func / class / var符号名称可以改变导入的包/模块中符号的值。