【发布时间】:2016-11-24 00:16:56
【问题描述】:
我怎样才能使模块内的模块.adipiscing.lorem_ipsum 可用,以一种干净地使用导入系统并且不会留下无关名称未使用?
给定一个代码库:
foo/
consecteur.py
adipiscing/
lorem_ipsum.py
consecteur 模块需要访问adipiscing.lorem_ipsum 模块。
这就是我想做的:
# consecteur.py
from . import adipiscing.lorem_ipsum
dolor = adipiscing.lorem_ipsum.dolor_sit_amet()
这行不通; from . import adipiscing.lorem_ipsum 是一个语法错误。
不满足的选项
使用隐式相对导入
# consecteur.py
import adipiscing.lorem_ipsum
dolor = adipiscing.lorem_ipsum.dolor_sit_amet()
这不必要地混淆了adipiscing.lorem_ipsum 是绝对导入还是相对导入。当导入是相对的时,代码应该是显式的。
将模块从其命名空间包中拉出
# consecteur.py
from .adipiscing import lorem_ipsum
dolor = lorem_ipsum.dolor_sit_amet()
这会丢失通过阅读 adipiscing.lorem_ipsum 传达的有价值的信息,尤其是如果 lorem_ipsum 是一个通用词,需要由 adipiscing 包命名空间上下文化。
使用错误名称导入
# consecteur.py
from .adipiscing import lorem_ipsum as adipiscing_lorem_ipsum
dolor = adipiscing_lorem_ipsum.dolor_sit_amet()
这在视觉上令人困惑;期待adipiscing.lorem_ipsum 的人可以轻松输入期待它工作的人,但该名称不可用。取一个容易混淆的名字并不是一个好的解决方案;两者都不是一个独特的名称,因为整个目的是使adipiscing.lorem_ipsum可用。
如果包或模块名称中的一个或两个实际上已经有下划线,这也是模棱两可的。如果下划线代表一个点,则它与实际包含下划线的名称无法区分。
导入包,尝试使用模块
# consecteur.py
from . import adipiscing
dolor = adipiscing.lorem_ipsum.dolor_sit_amet()
这是一个 AttributeError,因为 adipiscing.lorem_ipsum 现在不可用;仅通过导入包含的包,模块不会自动可用。
导入包,然后导入模块,但不要使用它的名字
# consecteur.py
from . import adipiscing
from .adipiscing import lorem_ipsum
dolor = adipiscing.lorem_ipsum.dolor_sit_amet()
这个 hack 成功了,但是 import 语句 from .adipiscing import lorem_ipsum 声明我们将使用纯 lorem_ipsum 名称。
由于这不是真的,静态代码检查器会(正确地)抱怨未使用的导入。我同意那些代码检查器,所以我不只是想消除警告;我想避免黑客攻击,并且仍然可以使用 adipiscing.lorem_ipsum 名称。
那么,我怎样才能使adipiscing.lorem_ipsum 名称可用于代码通过该名称,使用显式相对导入,没有未使用的导入强>?
【问题讨论】:
-
如果您担心代码检查器(即 flake8),只需将
# noqa: F401附加到行并注释您这样做的原因。 -
或者只使用完整的导入,因为这样可以完全消除事物的歧义并且更加明确。
-
或者,尝试在
from . import adipiscing之后查看,只需执行from adipiscing import lorem_ipsum,注意adipiscing缺少前导.
标签: python namespaces python-import