为什么要删除 __init__.py 中的模块?

Why delete modules in __init__.py?

我正在对 PyTorch 源代码进行一些研究。在 this file 中,作者实际上删除了模块。

from .adadelta import Adadelta  # noqa: F401
from .adagrad import Adagrad  # noqa: F401
from .adam import Adam  # noqa: F401

del adadelta
del adagrad
del adam

这样做的理由是什么?

这是一种在不使子模块成为 public API 的一部分的情况下将功能分解为子模块的方法。导入系统的一个怪癖是 this sort of relative import ends up putting the submodules in the parent's namespace,因此用户可以执行以下操作:

import torch.optim

然后访问 torch.optim.adadelta 的属性,而无需显式导入 torch.optim.adadelta。虽然一些 Python 内置包以这种方式工作,但它不会被撤消,因为太多人无意中依赖它(例如,只有 import os 的人,然后使用 os.path APIs), 通常最好避免这种数据泄漏。导入 torch.optim 应该只提供对列出的特定名称的访问,而不保证将自动导入哪些子模块。

通过这样做,人们不会意外地依赖于仅导入 torch.optim 后能够使用 torch.optim.adadelta,因此开发人员可以自由重构它以移动特定 类 和周围的其他 API,没有做出特别的努力来确保 import torch.optim 也导入所有这些子模块只是为了保留执行 improper/incomplete 导入的代码的行为。