import 机制
本节目标
学完这一节,你会知道:
- 什么是模块,什么是包
import有哪些常见写法- 如何创建自己的模块
if __name__ == "__main__"是什么- 如何避免常见导入错误
当一个文件越来越长时,就需要把代码拆到多个文件里。import 就是把别的文件里的代码拿过来用。
先跑一个例子
在同一个文件夹里创建两个文件。
utils.py:
def add(a, b):
return a + b
def greet(name):
return f"你好,{name}!"
main.py:
from utils import add, greet
print(add(3, 5))
print(greet("小明"))
运行:
python3 main.py
你会看到:
8
你好,小明!
main.py 导入并使用了 utils.py 里的函数。
什么是模块?
一个 .py 文件就是一个模块。
project/
├── main.py
└── utils.py
这里 utils.py 就是一个模块。
Python 自带很多模块,比如:
import math
import random
import json
你自己写的 .py 文件也可以被导入。
import 的常见写法
导入整个模块:
import math
print(math.sqrt(16))
导入模块里的某个函数:
from math import sqrt
print(sqrt(16))
导入并起别名:
import datetime as dt
print(dt.datetime.now())
不推荐:
from math import *
它会把很多名字直接放进当前文件,容易看不出函数来自哪里。
创建自己的模块
calculator.py:
def add(a, b):
return a + b
def multiply(a, b):
return a * b
main.py:
import calculator
print(calculator.add(3, 5))
print(calculator.multiply(4, 6))
也可以:
from calculator import add, multiply
print(add(3, 5))
print(multiply(4, 6))
如果模块名比较清楚,import calculator 反而更容易读。
什么是包?
包就是包含多个模块的文件夹。
my_project/
├── main.py
└── tools/
├── __init__.py
├── file_utils.py
└── string_utils.py
有 __init__.py 的文件夹通常可以当作包。
导入包里的模块:
from tools.file_utils import read_text
from tools.string_utils import clean_text
name 和 main
很多文件底部会写:
if __name__ == "__main__":
print("直接运行这个文件时才执行")
它的作用是:区分“直接运行”和“被别人导入”。
例子:
utils.py:
def add(a, b):
return a + b
if __name__ == "__main__":
print("测试 add 函数")
print(add(1, 2))
直接运行:
python3 utils.py
测试代码会执行。
被 main.py 导入时,测试代码不会执行。
模块搜索路径
导入模块时,Python 会去一些地方找:
- 当前运行目录
- 标准库目录
- 第三方库目录
- 环境变量指定的目录
可以查看:
import sys
for path in sys.path:
print(path)
刚入门时,最重要的是:自己写的模块最好和主程序放在清楚的项目结构里。
逐行拆解
再看开头的例子:
from utils import add, greet
从 utils.py 中导入 add 和 greet 两个函数。
print(add(3, 5))
调用导入的 add()。
如果写成:
import utils
调用时就要写:
utils.add(3, 5)
自己改一改
继续扩展两个文件。
utils.py:
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def greet(name):
return f"你好,{name}!"
main.py:
import utils
print(utils.add(10, 3))
print(utils.subtract(10, 3))
print(utils.greet("马哥"))
然后继续改:
- 增加一个
multiply()函数 - 在
main.py里调用它 - 给
utils.py加上if __name__ == "__main__"测试代码
常见错误
1. 文件名和标准库重名
不要把自己的文件命名为:
json.py
random.py
math.py
email.py
否则可能影响标准库导入。
2. 循环导入
a.py 导入 b.py,同时 b.py 又导入 a.py,可能造成循环导入。
解决思路:把共同代码放到第三个模块,或者重新整理依赖关系。
3. 被导入时执行了测试代码
把测试代码放进:
if __name__ == "__main__":
...
4. 路径结构混乱
如果导入失败,先确认文件是否在当前项目目录里,运行命令的位置是否正确。
小练习
练习 1:创建数学模块
创建 math_tools.py,里面写 add() 和 multiply(),再在 main.py 中导入使用。
练习 2:字符串工具
创建 string_tools.py,写一个 clean_text(text),返回去掉空白并转小写的字符串。
练习 3:模块自测
给 math_tools.py 加上 if __name__ == "__main__",直接运行时打印测试结果。
参考答案
练习 1:
math_tools.py:
def add(a, b):
return a + b
def multiply(a, b):
return a * b
main.py:
from math_tools import add, multiply
print(add(1, 2))
print(multiply(3, 4))
练习 2:
def clean_text(text):
return text.strip().lower()
练习 3:
if __name__ == "__main__":
print(add(1, 2))
print(multiply(3, 4))
小结
这一节你学会了:
- 一个
.py文件就是一个模块 import module和from module import name是最常见导入方式- 包可以把多个模块组织到文件夹里
if __name__ == "__main__"可以避免导入时执行测试代码- 文件名不要和标准库重名
下一节我们会学习常用标准库。Python 自带很多模块,能直接帮你处理时间、随机数、数学、路径等任务。
代码拆成多个文件,项目就开始长大了
import 的意义,是让每个文件各司其职,而不是把所有代码都堆成一锅粥。先从 utils.py 和 main.py 练起就够了。马哥的小提醒:别给文件起名 random.py、json.py,不然标准库会有点委屈。
还没有评论,来抢沙发吧!