python3.6 中__init__.py对于一个包来说是否是必须的?

在 python tutorial 中,我看到这样一句话:

The __init__.py files are required to make Python treat the directories as containing packages;

我在 pycharm 中像这样设置了文件目录的层次,其中 subdir1 没有 __init__.py,而 subdir2__init__.py。在 hello1.pyhello2.py 中,我都写了一个 hello 函数,然后从位于 subdir3 目录下的两个 test 程序中调用 hello 函数,结果都成功运行了。是不是意味着有没有 __init__.py 作用一样?都可以被位于其他目录下的程序 import?

图片描述

# test1.py
from subdir1 import hello1
hello1.hello()
# test2.py
from subdir2 import hello2
hello2.hello()
阅读 13.2k
5 个回答

从Python 3.3开始就不需要了,PEP 420相关说明

Native support for package directories that don’t require __init__.py marker files and can automatically span multiple path segments (inspired by various third party approaches to namespace packages, as described in PEP 420)

PEP 420链接:https://docs.python.org/3/wha...
参考:https://stackoverflow.com/que...

如果不添加__init__ python不会将其视作包,这个是包的初始化入口,当你第一次import该包时,会运行__init__。该包的__file__属性会指向__init__所在路径。

你这里说的没有__init__的是python3的新feature:命名空间包。这么写在python2中是报错的。

print(subdir2.__path__)
print(subdir2.__path__)

你可以看看区别。

Regular packages will continue to have an __init__.py and will reside in a single directory.

Namespace packages cannot contain an __init__.py. As a consequence, pkgutil.extend_path and pkg_resources.declare_namespace become obsolete for purposes of namespace package creation. There will be no marker file or directory for specifying a namespace package.

During import processing, the import machinery will continue to iterate over each directory in the parent path as it does in Python 3.2. While looking for a module or package named "foo", for each directory in the parent path:

If <directory>/foo/__init__.py is found, a regular package is imported and returned.
If not, but <directory>/foo.{py,pyc,so,pyd} is found, a module is imported and returned. The exact list of extension varies by platform and whether the -O flag is specified. The list here is representative.
If not, but <directory>/foo is found and is a directory, it is recorded and the scan continues with the next directory in the parent path.
Otherwise the scan continues with the next directory in the parent path.
If the scan completes without returning a module or package, and at least one directory was recorded, then a namespace package is created. The new namespace package:

Has a __path__ attribute set to an iterable of the path strings that were found and recorded during the scan.
Does not have a __file__ attribute.
Note that if "import foo" is executed and "foo" is found as a namespace package (using the above rules), then "foo" is immediately created as a package. The creation of the namespace package is not deferred until a sub-level import occurs.

A namespace package is not fundamentally different from a regular package. It is just a different way of creating packages. Once a namespace package is created, there is no functional difference between it and a regular package.

Python的设计理念是“一切皆对象”。所以,给人的感觉就是 python 包的构造器 __init__.py,或类的构造函数 __init.__() 是可有可无的。

但是,包的构造器 __init__.py或类的构造函数 __init.__() 也不是一无是处的,在其中,可有重新定义包或类里的子包,函数、属性的名称,使其按照自己的命名规范对外提供 api 服务等,详情可有自行必应

关于Python包和模块的区别,你可以简单的把包理解为windows的目录。包是模块的特例,典型的说。任何含有__path__ 属性的模块都可以认为是包

It’s important to keep in mind that all packages are modules, but not all modules are packages. Or put
another way, packages are just a special kind of module. Specifically, any module that contains a path
attribute is considered a package.

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏