python __init__文件的作用

学习路线:B站

1.没有__init__文件时

目录结构:

├── moduleA.py
└── main.py

moduleA.py的内容如下:

print("moduleA is imported")

main.py内容如下:

import moduleA

运行main.py会打印输出如下:

moduleA is imported

2.导入一个package

目录结构如下:

├── packageA
    └── moduleA.py
└── main.py

其中moduleA.py内容如下:

print("moduleA is imported")

main.py内容如下:

import packageA

运行main.py时,什么都不会打印。因为我们引入packageA并不会执行packageA中的moduleA.py,而是会执行一个__init__.py(目前我们还没有建立)。

3.重新导入package

目录结构如下:

├── packageA
    ├── __init__.py
    └── moduleA.py
└── main.py

其中__init__.py内容如下:

print("packageA is imported")

其中moduleA.py内容如下:

print("moduleA is imported")

main.py内容如下:

import packageA

运行main.py时,可以看到执行了__init__.py,输出:

packageA is imported

说明我们导入一个package时,会自动执行这个package中的__init__.py文件。

注意这里没有输出moduleA is imported说明,只是自动执行了__init__.py而不会自动执行moduleA.py

应该往__init__.py文件中放什么

  1. 包的初始化,有的包需要环境变量,有的包需要配置logging
  2. 包的公共接口,即包需要被外面使用的东西。

例如moduleA.py内容如下:

x = 'moduleA constant'

main.py内容如下:

from packageA import x

执行main.py会报错:ImportError: cannot import name ‘x’ from ‘packageA’


如果想要在main.py中导入moduleA.py中的变量,需要再packageA中的__init__.py添加相对导入:

from .moduleA import x

这样就可以在main.py中执行x了

有时候我们会在main.py中导入packageA中的所有内容,例如main.py内容如下:

from packageA import *

print(x)
print(moduleA.x)

packageA中的__init__.py内容如下:

from . import moduleA # 默认就有这一行,最好写上这一行,逻辑更清晰一些
from .moduleA import x
__all__ = ['moduleA', 'x']
print("packageA is imported")

moduleA.py内容如下:

print("moduleA is imported")
x = 'moduleA constant'

运行main.py时,输出结果如下:

moduleA is imported
packageA is imported
moduleA constant
moduleA constant

总之:

  • __all__ 变量控制 from package import * 的行为
# 即使没有 __all__ 也可以访问
print(moduleA.模块A中的变量)  # 可以正常输出(虽然能访问,但违反约定)

# 如果是通过 * 导入则无法访问
from packageA import *
print(moduleA中的变量)  # NameError(如果 __init__.py 没有在 __all__ 中暴露)
  • 当没有定义 __all__ 时,只会导入 __init__.py 中定义的名称
  • 使用 __all__ 可以明确暴露的模块/变量(推荐始终显式定义)

注意区别 from packageA.moduleA import xfrom packageA import x有什么区别:

  • from packageA.moduleA import x
    1. 明确从 packageA 包的 moduleA 模块导入符号 x ** (会执行__init__.py中的代码,同时也会会执行moduleA中的代码)**
    2. 要求 moduleA 必须存在且包含 x 属性
    3. 导入路径: packageA → moduleA → x
  • from packageA import x
    1. 尝试直接从 packageA 包的 __init__.py 导入符号 x (只会执行__init__.py中的代码)
    2. 需要 packageA/__init__.py 中存在 x 定义或显式导入(例如 from .moduleA import x )
    3. __init__.py 未导出 x ,会引发 ImportError
  1. 包的信息,如作者、版本
# __init__.py
__version__ = "1.0.0"
__author__ = "Your Name"
__license__ = "MIT"

4. Python 3.3+ 的隐式命名空间包

从 Python 3.3 开始,即使没有 __init__.py 文件,目录也会被识别为包(称为 namespace package)。但显式创建 __init__.py 仍然是推荐做法:

  • 支持传统包的明确初始化
  • 更方便定义包级属性/方法
  • 更好的IDE支持
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值