python 中 '__init__.py' 文件的作用

前言

最近面试腾讯侧开实习生,挂了。不过找实习还得继续不是。这次面试问到个python的知识点,python 中 __init__.py 文件的作用。现场答得不够好。经过学习后,在这里总结下。

理论

  1. python中。每个.py文件都是一个模块。把功能相近的几个模块放在同一个文件夹里,然后再加上名为__init__.py的空文件,一个简易的python包就创建好了。

  2. 创建好包之后,就可以按照正常的import package逻辑调用包了。具体见下面的测试部分。假设此时你想要在import这个包之后,自动的执行一些操作。这些操作写在__init__.py中就可以了。

  3. 我们在引用包时,经常为了方便起见,直接使用from package import *来一次性地导入package中的所有模块。这个时候就需要用到__init__.py中的另一个作用了。在__init__.py中添加一个属性__all__,这个属性是一个列表,包含了在导入当前包时,所有需要自动导入的模块。

测试

实际验证下刚刚所说的三个作用。
这里创建一个测试环境,整体的目录结构如下:
初始目录结构
可以看到这里定义了一个两个模块mod.pytest.pymod.py处于package文件夹内,现在先假装package是一个python包。

mod.pytest.py中的内容分别如下:

mod.py

test.py

测试第一个作用

在没有加入__init__.py文件时,运行test.py文件,运行出错:
没有__init__.py
package文件夹中加入__init__.py空文件,再次运行test.py文件,正确运行:
有__init__.py

但是这个时候你如果直接调用package.mod.m(),还是会报错:
调用错误

此时可通过两种方法解决这个问题:
1. 在__init__.py中加入import mod
加入import mod

正确运行:
加入import mod

  1. 改变调用的方式,改import packagefrom package import mod
    __init__.py为空

正确运行:
改调用方式

测试第二个作用

其实在第一个测试中已经用到了这个作用。就是刚刚所用到的解决直接调用package.mod.m()报错问题的第一个方法。
这里再简单演示下:

__init__.py

执行test.py结果

可以看到执行import package时自动执行了__init__.py中的print语句。

测试第三个作用

首先清空__init__.py文件,这里刚刚添加的print语句并步影响结果。清空只是为了突出问题。
直接运行test.py
错误
可以看到运行出错了。这里出错是因为没有在__init__.py中加入__all__属性。

添加一下:
添加__add__

正确运行:
正确运行

总结

本文到这里也就基本结束了。三个作用总结一下:

  • 标识一个文件夹为python
  • 添加导入时自动运行的语句
  • 通过添加__all__属性,增加对from package import mod语句的支持

好了,本文到此结束。祝大家面试成功,也祝我面试成功。

<think>我们正在讨论Python包中的__init__.py文件。根据引用[1]和引用[2],__init__.py文件的主要作用是将其所在的目录标记为Python包。这样,Python会将该目录视为一个包,允许我们使用import语句导入包中的模块。 引用[3]提到,在Python 3.3之前,__init__.py文件是必须的,即使它是空的。从Python 3.3开始,引入了隐式命名空间包,不再严格要求__init__.py文件,但为了兼容性和明确性,通常还是保留它。 此外,引用[2]和引用[4]指出,__init__.py文件可以包含初始化代码,例如批量导入模块,这样在导入包时,这些模块也会被导入。同时,它还可以定义__all__变量来控制from package import *的行为。 下面我将详细解释__init__.py的作用、用法和相关知识。 </think> ### Python包中`__init__.py`的作用、用法及相关知识 `__init__.py`是Python包的核心配置文件,主要作用如下: #### 一、核心作用 1. **标识包目录** 在Python 3.3之前,目录中包含`__init__.py`文件才会被识别为包(Package)。例如: ``` my_package/ ├── __init__.py # 使my_package成为可导入的包 ├── module1.py └── module2.py ``` 此时可通过`import my_package`导入[^1][^3]。 2. **初始化包代码** 当包被导入时,`__init__.py`会自动执行,常用于: ```python # __init__.py print("包初始化完成") # 导入包时打印消息 from . import module1 # 自动导入子模块[^2] ``` 3. **控制导入行为** - 使用`__all__`变量定义`from package import *`时导入的模块: ```python # __init__.py __all__ = ['module1'] # 仅导入module1 ``` - 避免命名冲突(如引用[4]所述,后导入的模块会覆盖同名对象)[^4]。 --- #### 二、进阶用法 1. **简化导入路径** 在`__init__.py`中预先导入常用对象: ```python # __init__.py from .module1 import ClassA, function_b ``` 用户可直接使用: ```python from my_package import ClassA # 无需写完整路径 ``` 2. **实现子包聚合** 组织多层包结构: ``` parent_package/ ├── __init__.py └── child_package/ ├── __init__.py └── utils.py ``` 在父级`__init__.py`中导入子包: ```python # parent_package/__init__.py from . import child_package ``` 3. **存放包级别变量** 定义包内共享的常量或配置: ```python # __init__.py VERSION = "1.0" CONFIG = {"env": "production"} ``` --- #### 三、注意事项 1. **空文件仍有效** 即使`__init__.py`内容为空,它仍能标识包目录(Python 3.3+中非必须,但推荐保留)[^3]。 2. **避免循环导入** 若包内模块相互引用,需在`__init__.py`中谨慎处理导入顺序。 3. **执行时机** 包被首次导入时执行`__init__.py`,且仅执行一次(后续导入复用缓存)。 --- #### 四、典型应用场景 - **框架开发**:Django/Flask通过`__init__.py`组织应用组件 - **SDK封装**:简化第三方调用接口 - **大型项目**:管理模块依赖和命名空间 > 提示:现代Python项目中,即使支持隐式命名空间包,显式添加`__init__.py`仍是最佳实践,可明确包边界并支持初始化逻辑[^3]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值