Python中常见的__init__.py是什么意思?详解Python import的方式和原理

简介: Python中常见的__init__.py是什么意思?详解Python import的方式和原理

1 什么是模块化编程?

工程模块化是指将具有一定共性的功能封装成一个模块,并对外暴露应用接口,方便其他工程直接调用而无需关注底层实现的思想,工程模块化可以避免工程中各种功能函数相互交杂、定义混乱不堪的情形,有助于提高系统可维护性。


在C/C++中,工程模块化的基础是函数头文件.h,其是专门存放函数声明的文件,这些函数声明的具体实现则分离到函数源文件.cpp或.c中,若干个头文件和源文件组成一个模块。


在Python中,工程模块化的基础则是 __init__.py文件

2 init.py文件的作用

__init__.py文件有如下作用:

  • 组织包,是Package的标识文件
# 目录结构
app
    |- pkg_1
        |- __init__.py
        |- moduleA.py    # fun1()
        |- moduleB.py
    |- pkg_2
        |- __init__.py
        |- test.py
# pkg_1 __init__.py
from pkg_1 import moduleA
# test.py中引用
import pkg_1
pkg_1.moduleA.fun1() # 运行成功
# 删除__init__.py运行失败

没有__init__.py就无法导入包


在__init__.py中定义__all__列表控制着包的导入行为

这里解释模糊导入的概念。模糊导入的句式为:from pkg import *

*为通配符,即导入包中的所有模块。若希望为包中的模块设置访问权限,即在模糊导入作用下选择性地引入模块,则需要在__init__.py中定义__all__列表。例如上例中,在pkg_1->__init__.py中定义__all__=["moduleA"],则在模糊导入时只引入模块moduleA而不会导入moduleB。因此__all__的作用是:在模块级别暴露接口,提供了公开(Public)接口的约定。


在__init__.py中导入其他包或模块,方便组织管理各个模块之间的引用

3 Python如何import第三方库

前面说到,Python包以__init__.py为标志,用于实现工程模块化,假设包组织结构的实例如下:

package
    |- subpackage1
        |- __init__.py
        |- moduleA.py       #fun1() fun2()
    |- subpackage2
        |- __init__.py
        |- moduleA.py       #fun1()
        |- moduleB.py       #fun3() fun4()

用虚拟文件夹的方式理解Python包。所有的包都可视作文件夹,其下包含模块或子包(子文件夹),模块中包含函数、类、变量等属性。当前路径位置可视作一个空白文件夹,关键字from理解为“打开”,关键字import理解为“导入”,必须指出:所有import相关操作都要落实到模块或属性。一般地,导入有如下方式:


import subpackage1.moduleA

此方式相当于把一个名为subpackage1的文件夹复制粘贴到当前路径下,文件夹只包含模块moduleA,即使subpackage1中可能还有其他模块,引用moduleA中的func1()需要subpackage1.moduleA.fun1(),即打开subpackage1文件夹,再使用模块moduleA中的属性fun1()。注意,如果仅import subpackage1,相当于只引入了一个空文件夹,此时无法调用fun1(),除非在__init__.py中提前导入了模块。


from subpackage1 import moduleA

此方式相当于打开一个名为subpackage1的文件夹,再将其中的模块moduleA复制粘贴到当前空白文件夹下,引用moduleA的fun1()需要moduleA.fun1()。这种方式下,还有from subpackage1 import *的句式可以引入包中的所有模块。


from subpackage.moduleA import fun1()

此方式相当于打开一个名为subpackage1的文件夹下的模块moduleA,再将其中的fun1()复制粘贴到当前空白文件夹,引用fun1()只需fun1()即可。


除了应用上述导入句式外,还需要注意当前文件的运行路径,如下所示为一个忽略路径因素造成的导入包报错,因为运行目录app\pkg_2\下没有文件pkg_1且环境变量中也不存在pkg_1。

app
    |- pkg_1
        |- __init__.py
        |- moduleA.py    # fun1()
    |- pkg_2
        |- __init__.py
        |- test.py
# test.py中引用
# from pkg_1.moduleA import fun1
# 执行如下
>>> python app\pkg_2\test.py
>>> from pkg_1.moduleA import fun1
ModuleNotFoundError: No module named 'pkg_1'

若需要保持运行目录不变,必须进行环境变量配置,在import pkg_1前先添加父级目录到python解释器的运行环境变量中,在pkg_2的父级目录app下可访问到pkg_1,具体实现上依赖于sysos

import sys, os
sys.path.append(os.path.realpath('..'))

综上所述,包的导入需要考虑两个因素:

  1. 从哪里导入,即运行路径和环境变量的配置问题;
  2. 如何导入,即使用何种import句式。
目录
相关文章
|
1月前
|
缓存 算法 测试技术
Python中的装饰器:原理与实践
【2月更文挑战第29天】 在Python编程领域,装饰器是一种强大的工具,它允许我们在不修改原始函数代码的情况下,增加或修改函数的行为。本文将深入探讨Python装饰器的概念、实现原理以及实际应用,帮助读者掌握这一技术并在实际项目中灵活运用。
|
1月前
|
数据采集 NoSQL Redis
Python爬虫-代理池原理和搭建
代理池架构,代理池的实现
42 0
|
1月前
|
Python
请解释 Python 中的生成器的工作原理。
【2月更文挑战第20天】【2月更文挑战第58篇】请解释 Python 中的生成器的工作原理。
|
1月前
|
Python 容器
解释一下Python中弱引用的工作原理。
解释一下Python中弱引用的工作原理。
36 2
|
1月前
|
数据可视化 数据挖掘 开发者
import有什么用,python中怎么使用import
import有什么用,python中怎么使用import
26 1
|
12天前
|
机器学习/深度学习 人工智能 算法
|
1月前
|
算法 开发者 Python
【Python 基础扫盲 】self参数、__init__方法和.__str__方法的用处和区别?
【Python 基础扫盲 】self参数、__init__方法和.__str__方法的用处和区别?
20 0
|
1月前
|
算法 Python
深入理解Python虚拟机:super超级魔法的背后原理
深入理解Python虚拟机:super超级魔法的背后原理
|
1月前
|
Python
Python中的装饰器:原理与应用
【2月更文挑战第27天】 装饰器在Python中是一种强大而灵活的工具,它允许我们在不修改原始函数代码的情况下,增加函数的功能。本文将深入探讨装饰器的原理,并通过实例展示如何在Python中使用装饰器。
9 2
|
1月前
|
缓存 Python
Python中的装饰器:原理与应用
【2月更文挑战第26天】 装饰器在Python中是一种强大且灵活的工具,它允许我们在不修改函数代码的情况下增强函数的功能。本文将深入探讨装饰器的原理,并通过实例展示如何在实际项目中应用装饰器。
12 4