为什么Python打包文档说包的__init__.py文件应该为空?

5
根据打包Python项目的文档,__init__.py应该是空的。我想知道为什么?因为我将某些对象放在__init__.py文件中,这些对象在Package中的每个模块中都被使用。在检查像importlib、multiprocessing等标准包的一堆__init.py__文件时,发现它们都有一堆代码在文件中。

2
对于这个简单示例项目而言,它应该是空的。这并不适用于其他项目,就像“def add_one(number): return number + 1”部分并不适用于所有项目一样。 - user2357112
4个回答

6
__init__.py的唯一目的是指示包含该文件的文件夹是一个包,并将该文件夹视为包,因此建议将其留空。
考虑以下层次结构:
foo
    __init__.py
    bar.py

当你使用from foo import bar或者import foo.bar时,Python解释器会在foo文件夹中查找__init__.py,如果它找到了,那么模块bar将被导入,否则不会被导入。然而,这种行为随着时间的推移已经发生了改变,即使__init__.py缺失,Python也可能成功地导入模块/包,但是请记住“Python之禅”:显式优于隐式,所以最好还是有一个__init__.py
但是,在某些情况下,如果您需要定义一些包级别的变量,可以在__init__.py文件中进行定义,那么包内所有的模块都可以使用这些变量。
实际上,如果您查看PEP 257,它提到__init__.py也可以包含关于包级别信息的文档。

确切地说,如果我们在这里考虑禅意,告诉读者“init应该是空的”对我来说意味着它应该始终为空。我认为它可以用更好的方式来表达。正如您所看到的,在这个线程中有一些相互矛盾的答案。 - pyeR_biz

1
你把那个语句理解得比它的本意更普遍了。你正在阅读教程中的一条语句,其中他们引导您创建一个简单的示例项目。那个特定的示例项目的__init__.py应该是空的,因为该示例不需要在__init__.py中执行任何操作。
大多数项目的__init__.py文件都不会是空的。以流行包(如numpyrequestsflasksortedcontainers或stdlib asyncio)为例,这些示例__init__.py文件都不为空。它们可能执行包初始化,将子模块中的内容导入到主包命名空间中,或包括元数据,如__all____version__或包docstring。示例项目只是简化到没有任何这些内容的程度。

我也是这么想的,但我认为教程文本不够清晰,可能会引起混淆。 - pyeR_biz

1
据我所知,创建非空的__init__文件时需要注意以下三点:
  • 代码可能更难理解。如果在__init__中实例化a = B(),情况会更糟。我知道有些开发人员因为这个原因而不喜欢它。
  • 在导入包时,将评估__init__的内容。有时它可能是计算密集型或根本不需要的。
  • 命名空间冲突。您无法真正在init中实例化bar并在包中拥有一个bar.py文件。

我喜欢在__init__中导入包的内容,否则在较大的项目中,导入语句会变得很丑陋。总体而言,这不是一种好或坏的做法。此建议仅适用于此特定示例中的项目。


-1
在某些情况下,您的软件包中可能没有任何共享组件。假设定义了一个小型软件包来计算一些算法,那么您就不需要在__init__中使用任何共享组件。

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