>>> 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() 命名空间dicts:
>>> 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 相同
好的,让我们检查它在 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() 开始's delete ' 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'>
>>>
并没有定义路径:
>>> globals()['path']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>
13 回答
import module
和from module import foo
之间的区别主要是主观的 . 选择你最喜欢的那个,并在使用它时保持一致 . 以下是一些可以帮助您做出决定的要点 .import module
Pros:
减少
import
陈述的维护 . 不需要添加任何其他导入即可开始使用模块中的其他项目Cons:
在代码中输入
module.foo
可能很乏味且冗余(使用import module as mo
然后输入mo.foo
可以最小化单调)from module import foo
Pros:
减少输入使用
foo
可以更好地控制可以访问模块的哪些项目
Cons:
要使用模块中的新项目,您必须更新
import
语句你丢失了关于
foo
的背景信息 . 例如,与math.ceil()
相比,ceil()
的作用还不太清楚两种方法都可以接受,但 don't 使用
from module import *
.对于任何合理的大型代码集,如果您
import *
,您可能会将其粘合到模块中,无法删除 . 这是因为很难确定代码中使用的项目来自'module',这使得很容易达到您认为不再使用import
的程度,但是很难确定 .这里有另一个细节,未提及,与写入模块有关 . 虽然这可能不是很常见,但我不时需要它 .
由于引用和名称绑定在Python中的工作方式,如果你想更新模块中的一些符号,比如foo.bar,从那个模块外部,并让其他导入代码“看到”更改,你必须导入foo a某种方式 . 例如:
模块foo:
模块a:
模块b:
但是,如果导入符号名称而不是模块名称,则不起作用 .
例如,如果我在模块a中执行此操作:
在a之外没有代码会看到bar为“oranges”,因为我的bar设置只影响了模块a中的名称“bar”,它没有“到达”foo模块对象并更新其“bar” .
即使很多人已经解释过
import
vsimport from
,但我想尝试更多地解释一下发生在幕后的事情,以及它所改变的所有地方 .import foo:
导入
foo
,并在当前名称空间中创建对该模块的引用 . 然后,您需要定义已完成的模块路径以从模块内部访问特定属性或方法 .例如 .
foo.bar
但不是bar
来自foo导入栏的
:
导入
foo
,并创建对列出的所有成员的引用(bar
) . 不设置变量foo
.例如 .
bar
但不是baz
或foo.baz
来自foo import *的
:
导入
foo
,并创建对当前命名空间中该模块定义的所有公共对象的引用(__all__
中列出的所有内容,如果__all__
存在,否则所有不以_
开头的内容) . 不设置变量foo
.例如 .
bar
和baz
但不是_qux
或foo._qux
.现在让我们看看
import X.Y
:检查名称为
os
和os.path
的sys.modules
:使用
os
和os.path
检查globals()
和locals()
命名空间dicts:从上面的例子中我们发现只有
os
被插入到本地和全局命名空间中 . 所以,我们应该可以使用:但不是
path
.从locals()命名空间中删除
os
后,即使它们存在于sys.modules中,您也无法访问os
以及os.path
:现在让我们来谈谈从:
来自:
使用os和os.path检查sys.modules:
我们发现在
sys.modules
中我们发现与之前使用import name
相同好的,让我们检查它在
locals()
和globals()
命名空间中的表现:您可以使用
path
而不是os.path
来访问:从
locals()
开始's delete ' path':使用别名的最后一个示例:
并没有定义路径:
支持这两种方式的原因有一个:有时候一个比另一个更合适 .
import module
:当您使用模块中的许多位时很好 . 缺点是您需要使用模块名称限定每个引用 .from module import ...
:很好,导入的项目可以直接使用,没有模块名称前缀 . 缺点是你必须列出你使用的每一件事,并且在代码中不清楚某些东西来自何处 .使用哪个取决于这使得代码清晰可读,并且与个人偏好有很多关系 . 我倾向于
import module
,因为在代码中,对象或函数的来源非常清楚 . 当我在代码中使用一些对象/函数时,我使用from module import ...
.我个人经常使用
然后访问所有内容
原因在于,您同时进行了短调用,并清楚地定义了每个例程的模块名称空间,如果您必须在源代码中搜索给定模块的使用,这一点非常有用 .
不用说,不要使用import *,因为它会污染你的命名空间,它不会告诉你给定函数的来源(来自哪个模块)
当然,如果两个不同的软件包中的两个不同模块具有相同的模块名称,则可能会遇到麻烦
在这种情况下,当然你会遇到麻烦,但是有一个强烈暗示你的包装布局存在缺陷,你必须重新考虑它 .
最好何时使用模块中的许多功能 .
当您只需要
function
时,最好避免使用模块中的所有函数和类型来污染全局命名空间 .这是另一个未提及的差异 . 这是从http://docs.python.org/2/tutorial/modules.html逐字复制的
请注意,使用时
该项可以是包的子模块(或子包),也可以是包中定义的其他名称,如函数,类或变量 . import语句首先测试是否在包中定义了该项;如果没有,它假定它是一个模块并尝试加载它 . 如果找不到它,则引发ImportError异常 .
相反,使用语法时
每个项目除了最后一个必须是一个包;最后一项可以是模块或包,但不能是前一项中定义的类或函数或变量 .
我刚刚发现了这两种方法之间的另一个细微差别 .
如果模块
foo
使用以下导入:然后模块
bar
错误地使用count
,好像它是在foo
中定义的,而不是在itertools
中:如果
foo
使用:错误仍然存在,但不太可能发生 .
bar
需要:这给我带来了一些麻烦 . 我有一个模块错误地从未定义它的模块导入了一个异常,只从其他模块导入它(使用
from module import SomeException
) . 当不再需要和删除导入时,违规模块被破坏 .为了增加人们对
from x import *
所说的内容:除了让人们更难分辨姓名来自何处之外,这还会抛出像Pylint这样的代码检查器 . 他们会将这些名称报告为未定义的变量 .使用
import
时,标记必须是模块(包含Python命令的文件)或包(sys.path
中包含文件__init__.py
的文件夹) .当有子包时:
文件夹(包)或文件(模块)的要求是相同的,但文件夹或文件必须在
package2
内,且必须在package1
内,并且package1
和package2
必须包含__init__.py
文件 . https://docs.python.org/2/tutorial/modules.html使用
from
导入样式:包或模块将包含
import
语句的文件的名称空间输入module
(或package
)而不是package1.package2.module
. 您始终可以绑定到更方便的名称:只有
from
导入样式允许您命名特定的函数或变量:是允许的,但是
不被允许 .
我自己的答案主要取决于首先,我只使用一两个不同的模块,我经常会使用 from ... import 因为它会减少文件其余部分的击键次数,但是如果我将使用许多不同的模块,我更喜欢 import ,因为这意味着每个模块引用都是自我记录的 . 我可以看到每个符号的来源,而不必去打猎 .
Usuaully我更喜欢普通导入的自我记录样式,只有当我输入模块名称的次数增加到10到20以上时,才会改为从...导入,即使只导入了一个模块 .
由于我也是初学者,我将尝试以一种简单的方式解释这一点:在Python中,我们有三种类型的
import
语句:1. Generic imports:
这种类型的导入是我个人最喜欢的,这种导入技术的唯一缺点是,如果你需要使用任何模块的功能,你必须使用以下语法:
当然,它增加了打字工作,但作为一个初学者,它将帮助你跟踪与之相关的模块和功能,(一个好的文本编辑器将显着减少打字工作,建议) .
Typing effort can be further reduced by using this import statement:
现在,您可以使用
m.sqrt()
而不是math.sqrt()
.2. Function imports:
如果您的代码只需要访问模块中的单个或几个函数,那么这种类型的导入是最合适的,但是对于使用模块中的任何新项,您必须更新import语句 .
3. Universal imports:
虽然它可以显着减少打字工作但不建议使用,因为它会使用模块中的各种函数填充代码,并且它们的名称可能与用户定义函数的名称冲突 . example:
如果你有自己名为sqrt的函数并导入数学,那么你的函数是安全的:有你的sqrt并且有math.sqrt . 但是,如果您使用math import *,则会出现问题:即两个具有完全相同名称的不同函数 . 来源:Codecademy
导入模块 - 您不需要额外的工作来从模块中获取另一个东西 . 它有诸如冗余打字之类的缺点
模块导入自 - 更少键入和更多控制可以访问模块的哪些项目 . 要使用模块中的新项目,您必须更新导入语句 .