1 组织结构
- Python项目的组织结构主要由包--模块--类这些部分构成。
- 包:可以看成文件夹,可以包含多个模块。如果让普通文件夹变成python的包,在该文件夹下必须包含init.py文件。
__init__.py
也是一个特殊的模块,模块名就是包名。 - 模块:可以看成文件,对应python中的.py文件。一个模块下面也可以包含多个类。模块下面也可以直接写函数。
- 类:类中定义了变量和函数。
- 函数:用于实现特定功能,
2. 模块导入
2.1 import
import只能引入模块,不能直接引入变量或函数。
示例:在main.py文件中导入包package1中的模块module1.py和module2.py。
import package1.module1
import package1.module2 as pm2 # 多层调用太长,可以重命名
print(package1.module1.var1)
print(pm2.num1)
# 输出
Python
1
2.2 from...import
可以导入模块、变量或函数。
- 导入模块
from package1 import module1
from package1 import module2
print(module1.var2)
print(module2.num2)
# 输出
Go
2
- 导入变量或函数
from package1.module1 import var3
print(var3)
# 输出
Java
- 导入模块下所有内容
from package1.module2 import * # 一般不建议使用*
print(num2)
# 输出
2
- 控制模块中对外暴露的内容
在module2.py
模块中定义了__all__=['num1', 'num2']
,则导入模块module2.py
时只可导入num1, num2
,其他内容不可见。
from package1.module2 import *
print(num3)
# 输出
NameError: name 'num3' is not defined
注意,__all__
属性仅在使用import *
时才有效。
from package1.module2 import num3
print(num3)
# 输出
3
- 导入模块换行
# 使用
from package1.module2 import num1,
num2, num3
# 使用(),推荐这种方式
from package1.module2 import (num1,
num2, num3)
2.3 包和模块导入注意点
- 包和模块不会重复导入:在导入一个模块的时候,就会执行这个模块里的所有内容,但是多次导入只执行一次。
- 不建议循环引入:多个模块文件间不建议相互调用,会导致报错。
2.4 相对导入和绝对导入
- 绝对导入:必须从顶级包开始。
- 相对导入:
.
表示当前目录,..
上一级目录。 - import不能使用相对导入,如import .package2.package4.m2。
- 入口文件不可以使用相对路径来导入模块,只能使用绝对路径。
- python -m main.py 将入口文件当作一个模块执行,则可以使用相对路径导入模块。
2.5 模块搜索路径
当我们导入模块时,默认情况下python解析器会搜索当前目录、已安装的内置模块和第三方模块,搜索路径存放在sys模块的path中。sys.path返回一个列表
import sys
print(sys.path)
当我们需要添加自定义的搜索目录时,使用如下命令:
import sys
sys.path.append('自定义模块的路径')
2.6 模块推荐导入顺序
在文件中需要导入内置模块、第三方模块或自定义模块时,建议的导入顺序是:标准库模块--第三方模块--自定义模块。
3 __init__.py
的用法
- 用来标识该文件夹是一个包。
- 导入包或包下的模块时,
__init__.py
文件被自动执行。 -
__init__.py
文件中也可以利用__all__
来限制导入的模块。
例如,在__init__.py
定义如下内容:
__all__ = ['module1']
在main.py中导入模块module2.py。
from package1 import *
print(module2.num1)
# 输出
NameError: name 'module2' is not defined
由于在__init__.py
文件中限制了导入的模块,module2.py
不能被导入。
- 批量导入模块
如果在项目中有模块是多个文件共用的,可以把这些模块在__init__.py
导入。
4 入口文件
Python 是脚本语言,和 C++、Java 最大的不同在于,不需要显式提供 main() 函数入口。在Python文件中,__name__ == '__main__'
被用于定义入口文件。这些文件既可以作为模块被导入,也可以执行。
if __name__ == '__main__':
pass
如果文件作为模块被导入,__name__
被赋值模块的名字。当文件执行被执行时,__name__
为__main__
。