95. Python __init__.py 使用
Python工程的组织结构
包、模块、类、函数、变量
- 最顶级的组织结构:包(文件夹)
- 第二个层级:模块(文件)
- 第三个层级:类
- 第四个层级:函数、变量(不属于组织结构,是类本身的特性)
其中:
- 包:整个文件夹
- 模块:一个
py
文件
Python包与模块的名字
区分不同包的同名模块:包名.模块名
形成的模块的路径叫做命名空间
一个包下面可以有子包,模块可以和包平级
普通文件夹想要变成包必须要有init.py文件__init__.py
本身也是一个模块,可以不写内容只是标注包
特殊地,__init__.py
模块的名字就是包名
__init__.py
用途
__init__.py
该文件的作用就是相当于把自身整个文件夹当作一个包来管理,每当有外部import的时候,就会自动执行里面的函数。
import导入模块
对于重复的定义需要从其他模块里引用。
利用import 模块名
导入
1 | # PackageTest1.Test1 |
import导入的总是模块,需要用模块名.变量名的方法引用
可以用as简化书写
1 | # PackageTest1.Test1 |
同级目录可以直接导入模块
优点是可以一眼看出属于哪个模块
from import 导入变量
1 | # PackageTest1.Test2 |
可以使用
from 包 import 模块
导入模块
导入时使用模块.变量
导入大量变量时用*
:
1 | # PackageTest1.Test1 |
控制 *
1 | # PackageTest1.Test1 |
注意
- 使用
*
导入时,导入的是在所在包中__init__.py
存在的变量 - 文件目录:
initTest
PackageTest1
__init__.py
Test1.py
Test2.py
Test.py
其中:
PackageTest1.__init__.py
1
2
3
4
5import pandas as pd
import numpy as np
print("You have imported mypackage")
# __all__ = ['pd', 'np'] # 这里不需要 __all__ 控制PackageTest1.Test1.py
1
2
3
4
5
6
7from __init__ import * # 可以使用所在包中的 __init__ 导入大量的包
class Test1():
def __init__(self):
a = np.array([i for i in range(10)])
print(a)Test.py
1
2
3
4from PackageTest1 import * # 因为 PackageTest1.__init__ 中只有 pd, np 这两个变量,因此使用 * 只导入进来了 pd, np
from PackageTest1.Test1 import Test1 # 因为在 PackageTest1.__init__ 中没有 Test1 这个模块,更没有 Test1 这个类,因此想要使用必须自行导入
Test1()
在 PackageTest1.__init__
中导入 Test1
模块、类
- 导入
Test1
模块
在PackageTest1.__init__.py
中添加import PackageTest1.Test1
就可以在Test.py
中使用Test1.Test1()
创建Test1
类了。 - 导入
Test1
类- 在
PackageTest1.__init__.py
中添加from PackageTest1.Test1 import Test1
就可以在Test.py
中使用Test1()
创建Test1
类了。 - 在
PackageTest1.__init__.py
中添加import PackageTest1.Test1
是错误的,会报错:ModuleNotFoundError: No module named 'PackageTest1.Test1.Test1'; 'PackageTest1.Test1' is not a package
- 在
__init__.py
用法
- 当包被导入时,
__init__.py
会首先被自动执行,类似于构造函数 __init__.py
的应用场景1
2
3
4
5
6
7
8
9
10
11# PackageTest1.__init__.py
__all__ = ['a','b'] #初始化*
import sys #批量导入库
import datetime
import io
#Test.py
import Test1
print(Test1.sys.path)此时引用因为不是用的
*
, 所以必须使用包.类.成员函数
进行调用。
多层目录各层互相调用
pacgage1
__init__.py
test1.py
test2.py
test3.py
test3
调用 package1
,而 test1
调用 test2
,此时,在 package1.__init__.py
中添加路径,如下:
1 | import sys |
包与模块的几个常见错误
- 包和模块是不会被重复导入的,只会执行一次(入口文件的概念)
- 避免循环导入,不要形成闭环
- 导入模块的时候会执行模块里所有的代码
- 如果使用
if __name__ == '__main__'
则不会执行该代码块中的代码