假设我使用具有以下结构的python包:
package/
bar.py
foo.py
__init__.py
bar.py
包含课程bar
,foo.py
包含函数foo
。
当我想导入函数/类时,我必须写
from package.bar import bar
from package.foo import foo
或者我可以写
from package import bar
from package import foo
更普遍的问: 当我导入一个与类/函数同名的模块时,我是否可以省略类/函数名称?
答案 0 :(得分:3)
不,您不能省略模块或对象名称。没有任何机制可以隐含地进行此类导入。
明确比隐含更好。
请注意,导入模块本身也应始终是有效选项。如果from package import bar
导入了package.bar.bar
对象,那么您必须尽量让自己访问package.bar
模块。
此外,这种隐式行为(自动导入模块中包含的对象而不是模块本身)会导致混淆不一致。
import package.bar
添加到命名空间的内容是什么?引用package.bar
是模块还是包含的对象? from package import bar
会给你模块吗?某些操作仍然会成功,导致奇怪的,难以调试的错误,而不是明确的ImportError
异常。一般来说,Python模块很少只包含一个的东西。 Python不是Java,模块由密切相关的对象组组成,而不仅仅是一个类或函数。
现在,包中存在固有的命名空间冲突; from package import foo
可以将package
模块,或上设置的名称引用到嵌套模块名称。在这种情况下,Python将首先查看package
命名空间。
这意味着您可以明确决定在foo
中的包级别提供bar
和package/__init__.py
个对象:
# in package/__init__.py
from .foo import foo
from .bar import bar
现在from package import foo
和from package import bar
将为您提供这些对象,屏蔽嵌套模块。
将子模块中的对象导入包命名空间的一般机制是组合公共API的常用方法,同时仍使用内部模块对逻辑进行分组。例如,Python标准库中的json.JSONDecodeError
exception在json.exceptions
模块中定义,然后导入json/__init__.py
。我通常会阻止屏蔽子模块;但是foo
和bar
加入了一个名称不同的模块。