鍍金池/ 問答/Python  Linux/ python3.6 中__init__.py對于一個包來說是否是必須的?

python3.6 中__init__.py對于一個包來說是否是必須的?

在 python tutorial 中,我看到這樣一句話:

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

我在 pycharm 中像這樣設(shè)置了文件目錄的層次,其中 subdir1 沒有 __init__.py,而 subdir2__init__.py。在 hello1.pyhello2.py 中,我都寫了一個 hello 函數(shù),然后從位于 subdir3 目錄下的兩個 test 程序中調(diào)用 hello 函數(shù),結(jié)果都成功運(yùn)行了。是不是意味著有沒有 __init__.py 作用一樣?都可以被位于其他目錄下的程序 import?

圖片描述

# test1.py
from subdir1 import hello1
hello1.hello()
# test2.py
from subdir2 import hello2
hello2.hello()
回答
編輯回答
初心

Python的設(shè)計理念是“一切皆對象”。所以,給人的感覺就是 python 包的構(gòu)造器 __init__.py,或類的構(gòu)造函數(shù) __init.__() 是可有可無的。

但是,包的構(gòu)造器 __init__.py或類的構(gòu)造函數(shù) __init.__() 也不是一無是處的,在其中,可有重新定義包或類里的子包,函數(shù)、屬性的名稱,使其按照自己的命名規(guī)范對外提供 api 服務(wù)等,詳情可有自行必應(yīng)。

2017年9月26日 02:27
編輯回答
祈歡

從Python 3.3開始就不需要了,PEP 420相關(guān)說明

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...

2018年4月8日 15:18
編輯回答
夏木

關(guān)于Python包和模塊的區(qū)別,你可以簡單的把包理解為windows的目錄。包是模塊的特例,典型的說。任何含有__path__ 屬性的模塊都可以認(rèn)為是包

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.

2018年2月2日 10:45
編輯回答
司令

如果不添加__init__ python不會將其視作包,這個是包的初始化入口,當(dāng)你第一次import該包時,會運(yùn)行__init__。該包的__file__屬性會指向__init__所在路徑。

你這里說的沒有__init__的是python3的新feature:命名空間包。這么寫在python2中是報錯的。

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

你可以看看區(qū)別。

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.
2018年3月7日 05:02
編輯回答
淡墨

必要的, 我覺得還有別的作用, 比如我自己總結(jié)過: https://juejin.im/post/5a2cfc...

2018年1月30日 19:44