Python Package中的 __init__.py

Package 中 init 的历史

在一些 Python 相关的项目时,常常会看到 __init__.py文件,
当你使用某些编辑器创建 Python Package 的时候,它也会自动给你生成一个 __init__.py 文件。
这玩意到底是干什么用的?

在这里插入图片描述
这个 py文件 里是空的
看名字,像是用来做一些初始化操作的,实际情况呢,其实也差不多

其实在 Python3.2 版本之前,定义的 Package 下面一定要有 __init__.py 文件,
这样 Python 才知道它是一个 Package,才可以寻找到相关模块的路径从而被 import

而在 Python3.2 之后的版本,
就不需要再额外的去专门创建一个 __init__.py 来告诉 Python 它是一个 Package 了,
因为现在创建的包叫 Namespace package, Python 可以自动搜寻 Package 路径,
哪怕你的父包路径发生了改变,你在下次导入的时候, Python 还是会自动重新搜索包路径。
所以现在如果 package 中没有定义 __init__.py,依然可以导入使用

Package 中 init 的作用

区分模块

在Python 中,一个 py文件,对应的就是一个模块。

在 my_package包 中创建三个子包 package_one、package_two、package_three
在这里插入图片描述

我们在编写的python程序中,不能同时导入两个同名的模块,而我们的程序又要用到这两个 py文件 里的内容,那么可以采用将这两个 py文件 放入两个不同的包下,通过导入不同包的方式进行区分,导入这两个不同的模块。

在 package_one 的 my_moudel 文件中定义类test1

class test1():

    print('*' * 10)

if __name__ == '__main__':
    pass

在 package_two 的 my_moudel 文件中定义类test2

class test2():

    print('*' * 20)

if __name__ == '__main__':
    pass

在 package_three 的 my_moudel 文件中定义类test3

class test3():

    print('*' * 30)

if __name__ == '__main__':
    pass

新建一个 my_print.py 文件,导入3个 my_moudel 模块

import my_package.package_one.my_moudel
import my_package.package_two.my_moudel
import my_package.package_three.my_moudel

f1 = my_package.package_one.my_moudel.test1
f2 = my_package.package_two.my_moudel.test2
f3 = my_package.package_three.my_moudel.test3

# 运行 my_print.py文件,结果为:

**********
********************
******************************
绑定到当前的命名空间

分别在子包的 init 文件中写入以下内容:

package_one

print('这是子包 one 的 init')

package_two

print('这是子包 two 的 init')

package_three

print('这是子包 three 的 init')

在父亲包 my_package 中写入以下内容:

print('这是父亲包 的 init')

新建一个 test.py 文件(可建在my_package 包外面),进行导包操作

只导入父模块 my_package

import my_package

# 运行test.py文件,结果为:

# 这是父亲包 的 init

总结:只导入父模块的时候只会执行父模块中的 init

单独导入子模块 package_one

import my_package.package_one

#  运行test.py文件,结果为:

# 这是父亲包 的 init
# 这是子包 three 的 init

单独导入package_two

import my_package.package_two

#  运行test.py文件,结果为:

# 这是父亲包 的 init
# 这是子包 two 的 init

单独导入package_three

import my_package.package_three

#  运行test.py文件,结果为:

# 这是父亲包 的 init
# 这是子包 three 的 init

三个包均导入

import my_package.package_one
import my_package.package_two
import my_package.package_three

#  运行test.py文件,结果为:

# 这是父亲包 的 init
# 这是子包 one 的 init
# 这是子包 two 的 init
# 这是子包 three 的 init

总结:导入父模块中的子模块的时候,优先执行父模块中的 init ,再执行指定模块中的 init

也就是说,当我们去 import 一个 Package 的时候,它会隐性的去执行 __init__.py , 
而在 __init__.py 中定义的对象,会被绑定到当前的命名空间里面来。

有时候我们会这样去导入一个包下的所有模块:

from my_package import *

# 运行test.py文件,结果为:

# 这是父亲包 的 init

但这个时候却并没有将相关的子模块导入进来,如果想采用这种导包的方式,也将子模块导入进来,或者导入某些特定的子模块进来,可采用对 父亲包的 init 文件进行编辑:

print('这是父亲包 的 init')

__all__ = ['package_one','package_three']

# 这里的 __all__ 相当于导入 [] 里面定义的模块

此时再运行 test.py 文件

from my_package import *

#  运行test.py文件,结果为:

# 这是父亲包 的 init
# 这是子包 one 的 init
# 这是子包 three 的 init
__init__.pyPython有一些限制和用法,具体如下: 1. __init__.py文件是一个特殊的文件,它用于将一个目录作为Python包进行导入。当一个目录被作为包导入时,Python会自动查找并执行该目录下的__init__.py文件。 2. __init__.py文件可以为空,但通常会包含一些初始化代码或者导入其他模块的语句。这些代码会在导入包时执行。 3. __init__.py文件可以包含任意Python代码,但是应该避免在其做过多的事情,以免导入包时产生额外的开销。 4. __init__.py文件的代码只会在第一次导入包时执行一次,后续导入同一个包时不会再次执行。 5. __init__.py文件可以用来定义包级别的变量、函数和类,这些定义可以在包的其他模块使用。 6. __init__.py文件还可以用来控制包的导入行为,例如在__init__.py使用\_\_all\_\_变量来指定导入时的可见性。 下面是一个示例,展示了一个包的结构和__init__.py文件的用法: ``` my_package/ __init__.py module1.py module2.py ``` __init__.py文件的代码可以是这样的: ```python # 导入其他模块 from .module1 import some_function from .module2 import MyClass # 定义包级别的变量 PI = 3.14159 # 定义包级别的函数 def some_other_function(): pass ``` 这样,在导入my_package时,__init__.py文件的代码会被执行,可以使用my_package.some_function()和my_package.MyClass来访问模块的函数和类。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值