Python 3.3+中__init__.py的用例

18
现在__init__.py不再是识别目录为包所必需的,那么最好能够避免使用它们吗?还是说在Python 3.3+中仍然存在着被广泛接受的使用情况?
据我所知,__init__.py通常用于在模块导入时运行代码(例如,封装软件包的内部文件结构或执行某些初始化步骤)。这些用例在Python 3.3+中是否仍然相关?

1
我唯一看到需要继续使用__init__.py的真正原因是为了向后兼容。 - Christian Dean
@leaf 那么我提到的这个示例怎么办?在Python 3.3+中有什么规范的方法来处理这个问题? - max
1个回答

6

这个问题在这个答案中有很好的讨论,你可能需要熟悉PEP 420以澄清普通包(使用__init__.py)和命名空间包(不使用)之间的区别。

我提供的回答是阅读、参考和观点的结合。这里没有声称是“规范”的或“pythonic”的。

在 Python 3.3+ 中,初始化用例是否仍然相关?

是的。以你的示例为例,包作者希望将几个东西带入根包命名空间,以便用户不必关心其内部结构。

另一种情况是创建一个模块的hierarchy。那个引用(O'Reilly)实际上说:
“__init__.py文件的目的是在遇到包的不同级别时包含可选初始化代码。”
他们确实在讨论中考虑了命名空间包,但接着说:
“如果刚开始创建新包,请包括__init__.py文件。”
所以针对你的第二个问题,
“如果可能的话,避免使用__init__.py是否是最佳实践?” 不是,除非你打算创建一个命名空间包而不是常规包,在这种情况下,你必须不使用__init__.py。

为什么你想要那个?O'Reilly参考资料中有关于为什么命名空间包很酷的最清晰的示例,这使得可以从不同的、独立维护的包中折叠命名空间:

foo-package/
    spam/
        blah.py

bar-package/
    spam/
        grok.py

这允许

>>> import sys
>>> sys.path.extend(['foo-package', 'bar-package'])
>>> import spam.blah
>>> import spam.grok
>>>

所以任何人都可以使用自己的代码扩展命名空间。很酷。


1
那么,也许最好的做法是尽可能避免使用“_packages_”,而改用“_namespaces_”?或者这种方法存在问题吗? - max
1
命名空间的优点似乎在于它们是可扩展的。它们的缺点是您不能在其中拥有__init__.py,因此无法执行某些操作(例如封装文件结构、执行初始化等)。这听起来正确吗? - max

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接