我正在学习Python,我不知道__init__.py
中的导入是如何工作的。
我从the Python tutorial了解到,__init__.py
文件初始化了一个包,我可以在这里导入子包。
不过,我做错了。你能为我(以及未来的Python学习者)解释一下我做错了什么吗?
这里有一个简单的例子来说明我要做的事情。
这是我的文件结构:
package
__init__.py
test.py
subpackage
__init__.py
hello_world.py
hello_world.py
的内容:
def do_something():
print "Hello, world!"
subpackage/__init__.py
为空。
package/__init__.py
包含:
import test.submodule.do_something
最后,test.py
包含:
do_something()
这就是我如何尝试使用OSX终端和Python3运行hello_world.py:
python test.py
然后,Python抛出以下错误:
NameError: name 'do_something' is not defined
首先,您必须了解
import
单独工作的方式:试图从
submodule
加载do_something
本身从test
加载。你想从
subpackage
加载一些内容,那么从这个开始:很好,
subpackage/__init__.py
已加载。现在,您需要文件中的
do_something()
函数(一个“模块”)hello_world.py
。简单:你完了!只要大声读这一行,它就会按它所说的做:从
subpackage
包中的模块hello_world
导入do_something
。在
test.py
中尝试它应该工作得很好。
现在,第二期:
__init__.py
不会在package/
中调用,因为您不使用package/
作为包。__init__.py
将用于导入package/
或其中的任何内容,例如:否则,它根本不会加载。
但是,如果要在导入子包时加载
do_something()
,请将from submodule.hello_word import do_something
放入subpackage/__init__.py
,然后在test.py
中执行import subpackage
。您可能已经理解了,当导入模块时,解释器将创建一个新的名称空间,并使用新名称空间作为本地和全局名称空间来执行该模块的代码。当代码完成执行时,模块名(或任何
as
子句中给定的名称)将绑定到刚在导入命名空间中创建并记录在其sys.modules
中的__name__
中的模块对象。当一个限定名(如
package.subpackage.module
)被导入时,第一个名(package
)被导入本地命名空间,然后subpackage
被导入package
的命名空间,最后module
被导入package.subpackage
的命名空间。使用from ... import ... as ...
的导入执行相同的操作序列,但导入的对象直接绑定到导入模块命名空间中的名称。包名没有绑定在本地命名空间中并不意味着它没有被导入(正如对sys.modules
的检查将显示的那样)。包中的
__init__.py
与模块的.py
文件的功能几乎相同。具有结构的包被编写为一个目录,该目录还可以包含任何子包的模块(常规.py
文件)和子目录(也包含__init__.py
文件)。导入包时,将创建一个新的命名空间,并使用该命名空间作为本地和全局命名空间来执行包的__init__.py
。因此,为了解决您的问题,我们可以通过省略顶级包来删除您的文件存储,当test.py
作为程序运行时,解释器永远不会考虑这个顶级包。然后看起来像这样:现在,
subpackage
不再是子包,因为我们已经删除了不相关的包含包。关注do_something
名称未定义的原因可能会有所帮助。test.py
不包含任何导入,因此不清楚您期望do_something
如何获得意义。您可以使用空的subpackage/__init__.py
使其工作,然后test.py
可以读取或者你可以给我们一个
subpackage/__init__.py
,上面写着它在导入包时在
subpackage
命名空间内建立do_something
函数。然后使用从包中导入函数的test.py
,如下所示:使用相同
__init__.py
的最后一种方法是使用test.py
,该方法只需导入(子)包,然后使用相对命名来访问所需的函数:在本地命名空间中访问它
空的
__init__.py
也可以通过读取test.py
来实现甚至
归根结底,最好的工具是清楚地了解import是如何工作的,以及它的各种形式对导入名称空间有什么影响。
在Python中,名称必须始终在使用它的模块中定义或导入,这是一个绝对严格且快速的规则。在这里,您永远不会在test.py中导入任何内容,因此正如错误所说,
do_something
未定义。即使您的
package/__init__.py
文件已被执行(正如其他人指出的那样,它没有执行),您的代码仍然无法正常工作,因为如果要在该文件中引用do_something
的导入必须在test.py中完成。相关问题 更多 >
编程相关推荐