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支持
Python中,`__init__.py`文件是一个特殊的文件,用于将一个目录标识为一个Python包。它可以是一个空文件,也可以包含包的初始化代码和变量。以下是`__init__.py`文件的一些主要用途和功能: 1. **标识包**:当一个目录中包含`__init__.py`文件时,Python会将其识别为一个包。这允许你使用`import`语句导入该包中的模块。 2. **初始化代码**:可以在`__init__.py`文件中编写初始化代码,这些代码在包被导入时会自动执行。这对于设置包的初始状态或导入子模块非常有用。 3. **导出接口**:通过在`__init__.py`文件中定义`__all__`列表,可以指定包中哪些模块或对象可以被导入。这有助于控制包的公共接口。 4. **子包导入**:可以在`__init__.py`文件中导入子包或子模块,使得用户可以通过顶级包名直接访问这些子包或子模块。 以下是一个简单的示例,展示了如何使用`__init__.py`文件: 假设有一个名为`mypackage`的包,其结构如下: ``` mypackage/ __init__.py module1.py module2.py ``` 在`__init__.py`文件中,可以这样编写: ```python # __init__.py # 导入子模块 from . import module1 from . import module2 # 定义__all__列表,指定公共接口 __all__ = ['module1', 'module2', 'function1', 'Class1'] # 从子模块中导入函数和类 from .module1 import function1 from .module2 import Class1 ``` 这样,用户可以通过以下方式导入包中的内容: ```python import mypackage # 使用子模块 mypackage.module1.function1() # 使用从__init__.py中导入的函数和类 mypackage.function1() instance = mypackage.Class1() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值