在Python中,如果你需要来自不同包的模块,你必须先导入它。对于来自Java背景的人来说,这是很合理的。
import foo.bar
然而,令人困惑的是每次想要使用bar时为什么需要使用完整名称?如果我想使用完整名称,为什么还需要进行导入操作呢?不是直接使用完整名称就可以描述我正在使用哪个模块吗?
这似乎有点多余,因为import foo.bar
应该已经做了from foo import bar
所做的事情。同时也有点含糊,因为我打算使用完整名称时为什么还需要导入。
在Python中,如果你需要来自不同包的模块,你必须先导入它。对于来自Java背景的人来说,这是很合理的。
import foo.bar
然而,令人困惑的是每次想要使用bar时为什么需要使用完整名称?如果我想使用完整名称,为什么还需要进行导入操作呢?不是直接使用完整名称就可以描述我正在使用哪个模块吗?
这似乎有点多余,因为import foo.bar
应该已经做了from foo import bar
所做的事情。同时也有点含糊,因为我打算使用完整名称时为什么还需要导入。
事实上,尽管Python的import
语句看起来与Java的相似,但它们在底层执行完全不同的操作。正如您所知,在Java中,import
语句仅仅是对编译器的一种提示。它基本上为完全限定类名设置了一个别名。例如,当你写下:
import java.util.Set;
它告诉编译器在该文件中,当你写 Set
时,你指的是 java.util.Set
。如果你写了 s.add(o)
,其中 s
是类型为 Set
的对象,那么编译器(或链接器)会查找 Set.class
中的 add
方法并将其引用插入其中。
但在Python中,
import util.set
(顺便说一下,那是一个虚构的模块)执行了完全不同的操作。在Python中,包和模块不仅仅是名称,它们实际上是对象。当你在代码中写util.set
时,这会告诉Python去访问一个名为util
的对象并查找其上名为set
的属性。Python的import
语句的工作是创建该对象和属性。它的工作原理是解释器寻找一个名为util/__init__.py
的文件,使用其中的代码来定义对象的属性,并将该对象绑定到名称util
上。类似地,util/set.py
中的代码将用于初始化一个对象,该对象绑定到util.set
上。有一个名为__import__
的函数来处理所有这些,实际上import util.set
语句基本上相当于:
util = __import__('util.set')
当你导入一个Python模块时,获得的是对应顶级包'util'的对象。要访问util.set,需要通过这个对象,这就是为什么在Python中似乎需要使用完全限定名称的原因。set = util.set
从那个时候起,您只需在原本编写util.set
的地方使用set
即可。(当然,这会混淆内置的set
类,所以我不建议实际使用set
这个名称。)或者,如至少另一个答案中提到的那样,您可以编写
from util import set
或者
import util.set as set
这仍然导入了包含模块set
的util
包,但是它不会在当前作用域中创建一个util
变量,而是创建一个set
变量,它指向util.set
。在幕后,这种方法的工作方式有点像:
_util = __import__('util', fromlist='set')
set = _util.set
del _util
在前一种情况下,或者
_util = __import__('util.set')
set = _util.set
del _util
尽管两种方式都实现了相同的功能,但后一种形式在语义上更像Java的import
语句:它定义了一个别名(set
),用于访问通常只能通过完全限定名称(util.set
)才能访问的内容。
import foo.bar as whateveriwant
from foo import bar
稍微冗长一些。"import foo.bar as bar" == 21 个字符,"from foo import bar" == 19 个字符。 - JABbar
是一个模块时,import a.b as c
语法才能生效。如果b是一个方法或变量,则该语法无法使用。实际上,您无法使用点符号导入方法或变量。您必须使用from ... import ...
语法,或通过包含模块名称引用该方法或变量。 - JAB标准库中有一个名为io
的模块:
In [84]: import io
In [85]: io
Out[85]: <module 'io' from '/usr/lib/python2.6/io.pyc'>
在 scipy
中还有一个叫做 io
的模块:
In [95]: import scipy.io
In [96]: scipy.io
Out[96]: <module 'scipy.io' from '/usr/lib/python2.6/dist-packages/scipy/io/__init__.pyc'>
In [97]: import this
The Zen of Python, by Tim Peters
...
Namespaces are one honking great idea -- let's do more of those!
math.sqrt(5)
,而不先导入math
或math.sqrt
,看看会发生什么。
无论如何... import foo.bar
要求您使用foo.bar
而不是只使用bar
,其原因是为了防止意外的命名空间冲突。例如,如果您执行import foo.bar
,然后执行import baz.bar
呢?
当然,您可以选择使用import foo.bar as bar
(即别名),但如果您这样做,您可能会选择使用from foo import bar
。(编辑:除非您想要导入方法和变量。那时您必须使用from ... import ...
语法。这包括您想要导入一个方法或变量而不使用别名的情况,例如,如果bar
是一个方法或变量,您不能简单地执行import foo.bar
。)
from
并在导入的模块中进行某些修改时,据我所记,这种更改不会传递到导入该模块的其他模块。但我可能是在凭空想象并混淆了什么,我一直无法找到证明。 - Philippfrom
来导入模块,因为它的主要目的是用于方法和变量/常量,这些不能直接使用通常的import
语法导入。 - JAB__init__.py
文件中的代码仅在第一次导入时执行。这很好。 - JAB您不必使用全名。可以尝试使用以下其中一个
from foo import bar
import foo.bar as bar
import foo.bar
bar = foo.bar
from foo import *
除了Java之外,在Python中,import foo.bar
声明你将使用由foo.bar
引用的东西。
这符合Python的哲学,即显式优于隐式。有更多的编程语言比Java更明确地表达模块间依赖关系,例如Ada。
使用完整名称可以消除来自不同模块的具有相同名称的定义的歧义。