【发布时间】:2015-07-26 04:42:10
【问题描述】:
考虑以下三个常规包的层次结构及其 内容:
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 说 推荐绝对进口:当它说绝对是什么意思 进口的表现比相对的好?你能给我一个 例子?
【问题讨论】:
-
您确定
jump属于dog.py,而不是更高层级吗? -
是的,我认为
lazy是某种连贯的组件集合,其中一些在quick的其他地方也需要。 -
我建议明确一点,尽可能简单。随着时间的推移,包内导入会变得有点疯狂。所以忘记所有
__init__.py魔法吧。如果你真的想要,你可以只在顶级__init__.py中为外部用户可见名称执行此操作。