复杂包结构中的 Python 导入语句?

标签 python import

考虑以下三个常规包的层次结构及其 内容:

quick
├── brown
│   ├── fox.py
│   └── __init__.py
├── lazy
│   ├── dog.py
│   └── __init__.py
└── __init__.py

现在假设在模块dog 中有一个函数jump,并且在模块fox 中需要它。我应该如何进行?

最近看过 Raymond Hettinger 的 talk at Pycon 2015我愿意 可直接从包 lazy 的根导入的函数, 像这样:

from lazy import jump 

另外,在我看来,写相对导入更简洁 使包内连接很容易看到。因此,我会写 这进入 lazy/__init__.py:

from .dog import jump

并将其放入 fox.py:

from ..lazy import jump

但我想知道,这是正确的方法吗?

首先,在 lazy/__init__.py 中导入名称 jump 对 防止它直接从 dog 导入。如果一个函数可能从许多地方导入,它会导致问题吗?例如,在单元测试中,我们是否可以从错误的位置修补名称?

此外,具有自动导入例程的 IDE 似乎更喜欢从定义函数的模块中导入。我或许可以通过将字符 _ 放在所有模块名称的前面来覆盖它,但这似乎有点不切实际。

将所有需要的名字带出 打包到 __init__.py?可能这至少增加了 循环进口的可能性。但我想如果一个通告 import 遇到了一些根本性的错误 无论如何包结构。

相对进口呢? PEP 8说 建议绝对进口:绝对进口是什么意思 进口产品表现优于相关产品?你能给我一个 例子?

最佳答案

显式接口(interface)声明:如果您想将jump 函数公开为属于lazy 包,那么包含它是有意义的lazy.__init__ ,正如你所建议的。这样你就清楚地表明它是 lazy 的“public interface”的一部分。您还建议其他模块不是公共(public)接口(interface)的一部分。

关于防止人/工具直接从dog导入:在Python中,隐私取决于用户是否同意,你不能强行隐藏任何东西,但有惯例。

使用下划线和定义 dog._jump() 可以清楚地表明 dog想要暴露 _jump。我们可以假设任何 IDE 工具都应该遵守这种约定。无论如何,如果 dog 定义了 _jump,并且 lazy 公开了 jump,那么您就不会有问题不知道导入的是哪个,因为名称不同,所以这是显式的,这在 Python 中被认为是好的。

这是关于这个主题的一个很好的指针:Defining private module functions in python

关于相对导入::PEP 8 不鼓励这些,但是它们的实现是有原因的,并且它们取代了隐式相对导入。 PEP 8 中的原因:尤其是在处理复杂的包布局时,在这种情况下使用绝对导入会不必要地冗长

最后的想法:简而言之,如果您将 lazy 包视为一个库并且不想暴露内部模块,那么我认为这是有道理的公开 lazy.__init__ 中的对象。相反,如果你想让人们知道有一个 dog 模块,那么无论如何,让其他模块做:

从 lazy.dog 导入跳转

从..lazy导入跳转

如果 brownbrown.fox 将始终被打包并与 lazy 紧密集成,那么我看不出绝对的区别和相对的,但我更喜欢相对的,以明确指示您指的是内部模块。

但如果你认为它们将来可能被拆分,那么相对导入就没有意义,你宁愿这样做,取决于以上几点:

from lazy.dog import jump
或者:
从惰性导入跳转

关于复杂包结构中的 Python 导入语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30239475/

相关文章:

MySQL:从 CSV 中获取列标题名称

java - 对于任何程序,我必须在 Java 中使用哪些常见导入?

javascript - 使用react js、babel和es6导入随机文件

java - 如何在 Eclipse 中导入外部 jar 文件并将项目导出为文件系统

java - 如何使用 solr 索引 sqlite 数据库

Python:对长数中的数字求和

python - opencv : getPixel() not reflecting drawRectangle()

python - lxml 更改 Unicode 字符

python - flask 错误处理程序

python - 我可以在多线程程序中嵌入多个 Python 解释器副本吗?