“导入模块”或“从模块导入”
我试图find一个关于是最好使用import module
还是from module import
的综合指南。 我刚刚开始使用Python,打算用Django开发Web应用程序,我试着从头开始学习最佳实践。
基本上,我希望如果有人能分享他们的经验,其他开发者有什么样的偏好,以及什么是避免任何问题的最好方法。
import module
和from module import foo
的区别主要是主观的。 select一个你最喜欢的,并保持一致的使用它。 这里有几点可以帮助你决定。
import module
- 优点:
- 减less维护您的
import
报表。 不需要添加任何额外的导入来开始使用模块中的其他项目
- 减less维护您的
- 缺点:
- 在你的代码中input
module.foo
可能是单调乏味的(冗长的,可以通过使用import module as mo
来最小化,然后inputmo.foo
)
- 在你的代码中input
from module import foo
- 优点:
- 减less打字使用
foo
- 更多的控制模块的哪些项目可以被访问
- 减less打字使用
- 缺点:
- 要使用模块中的新项目,您必须更新
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
使用名称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'>
使用名称os
和os.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 name
find了和之前一样的东西
好的,让我们看看它在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个不同的模块。 如果我只打算使用一个或两个,我会经常使用from
… import
因为它在文件的其余部分减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__.py
的sys.path
中的一个文件夹)。
当有子包时:
import package1.package2.package import package1.package2.module
文件夹(包)或文件(模块)的要求是相同的,但文件夹或文件必须位于package2
,必须位于package1
,并且package1
和package2
必须包含__init__.py
文件。 https://docs.python.org/2/tutorial/modules.html
from
import的风格:
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
只有from
import的风格,你可以命名一个特定的function或variables:
from package3.module import some_function
是允许的,但是
import package3.module.some_function
不允许。
导入模块 – 您不需要额外的努力从模块中获取其他东西。 它有缺点,如多余的打字
模块导入 – 减lessinput和更多的控制模块的哪些项目可以访问。要使用模块中的新项目,您必须更新您的导入语句。
两个区别在这里:1.只有“from … import …”才能导入func / class / var符号名称; 2.只有当导入的func / class / var符号名称可以改变导入的包/模块中符号的值。