模块和导入
模块就是一个装着 Python 代码、能给别的程序用的文件。Python 自带几百个,合起来叫标准库:算数学、处理日期、读写文件、随机数……早就有人写好、测好了。第 3 课已经见过一个:
1import math2 3print(math.sqrt(16))4print(math.pi)5print(math.ceil(7 / 3))
4.0 3.141592653589793 3
import math 把模块加载一次,给你一个名字 math。里面的东西都用点来拿:math.sqrt、math.pi。import 写在文件最上面,读代码的人一眼就能看出程序用了哪些模块。
import
可以一行导入好几个模块,比如 import math, statistics,也可以一行一个(更常见)。下面用 statistics 算一组数常用的几种平均:
1import statistics2 3ore = [12, 7, 9, 12, 5]4print(statistics.mean(ore))5print(statistics.median(ore))6print(statistics.mode(ore))
9 9 12
| 函数 | 返回 |
|---|---|
mean | 平均数:总和除以个数 |
median | 中位数:排好序以后中间那个 |
mode | 众数:出现次数最多的那个 |
前面带着模块名,意思很清楚:statistics.mean 不会和你自己写的 mean 函数搞混。
from、import 和 as
from 模块 import 名字 只把这个名字拿进来,用的时候不用再写模块名和点。as 给模块或名字起一个更短、更清楚的名字。
1from math import sqrt, pi2import statistics as stats3import datetime as dt4 5print(sqrt(81))6print(round(pi, 2))7print(stats.mean([2, 4, 9]))8print(dt.date(2026, 11, 1))
9.0 3.14 5 2026-11-01
| 这样写 | 之后这样用 |
|---|---|
import math | math.sqrt(9) |
from math import sqrt | sqrt(9) |
import statistics as stats | stats.mean(...) |
from math import * | math 里所有的名字,不用前缀;最好别用,看不出一个名字是从哪来的 |
会怎么样?
1import math2 3print(math.ceil(2.5))4print(ceil(4.2))
import math 给你的是 math 这个名字,不是它里面的名字。第一个 print 没问题;第二个碰到不认识的名字 ceil,停了。要写 math.ceil,或者再加一句 from math import ceil。
几个好用的模块
| 模块 | 干什么用 | 例子 |
|---|---|---|
random | 随机数、随机挑 | random.randint(1, 6) |
statistics | 平均数和离散程度 | statistics.median(xs) |
collections | 更多容器:Counter、defaultdict、deque、namedtuple | Counter(words) |
string | 现成的字母、数字、标点字符串 | string.digits |
time | 时钟,还有等一会儿 | time.sleep(1) |
math | 开平方、向上向下取整、圆周率 | math.floor(2.7) |
random 每次运行挑出来的都不一样,所以这里只检查结果是什么样的。多运行几次:背后的数在变,显示的结果不变。
1import random2 3roll = random.randint(1, 6)4print(1 <= roll <= 6)5lamp = random.choice(["榆树街", "橡树巷", "磨坊路"])6print(lamp in ["榆树街", "橡树巷", "磨坊路"])7rolls = [random.randint(1, 6) for i in range(10)]8print(len(rolls))9print(min(rolls) >= 1 and max(rolls) <= 6)
True True 10 True
randint(a, b) 给一个从 a 到 b 的整数,两头都包括;choice 从列表里挑一个。这个模块里还有别的,比如把列表打乱的 shuffle。collections 里的容器,计数、分组的时候能省不少事:
1from collections import Counter, defaultdict2 3loads = ["矿石", "灯油", "矿石", "灯芯", "矿石", "灯油"]4counts = Counter(loads)5print(counts["矿石"])6print(counts.most_common(2))7 8by_letter = defaultdict(list)9for item in ["oak", "elm", "oil", "ash"]:10 by_letter[item[0]].append(item)11print(dict(by_letter))
3
[('矿石', 3), ('灯油', 2)]
{'o': ['oak', 'oil'], 'e': ['elm'], 'a': ['ash']}
Counter 帮你数数,就像第 11 课用字典计数的那个循环。defaultdict(list) 碰到没见过的键,自动给一个空列表,所以可以直接 append。再看 string 和 time:
1import string2import time3 4print(string.ascii_uppercase)5print(string.digits)6code = "LAMP42"7print(all([c in string.ascii_uppercase + string.digits for c in code]))8 9start = time.time()10total = sum(range(100000))11print(time.time() - start >= 0)
ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 True True
time.time() 是从 1970 年起到现在的秒数,每时每刻都在变。干活之前取一次,干完再取一次,差就是这活花了多久;第 25 课再多讲时间。all([...]) 在列表里每一项都为真时给出 True。
看看模块里有什么
在你自己的电脑上,Python 的交互模式(在终端里输入 python)能告诉你。dir() 列出模块里的名字,help() 说明其中一个是干什么的:
1import math2dir(math) # ['acos', 'ceil', 'floor', 'pi', 'sqrt', ...]3help(math.ceil) # ceil(x, /) Return the ceiling of x ...
这两个在这里的浏览器例子里用不了。另一个地方是官方文档 docs.python.org,标准库里每个模块都有一页。
自己写模块
任何一个 .py 文件都是模块。程序越写越长,就拆成几个文件,用文件名(不带 .py)从一个文件导入另一个。比如你电脑上的同一个文件夹里有这两个文件:
1PRICE = 42 3def cost(count):4 return count * PRICE5 6def label(street):7 return street + "的灯"
1import lamps2from lamps import label3 4print(lamps.cost(3))5print(label("榆树街"))
运行 main.py,Python 在旁边找到 lamps.py,把它跑一次,里面的名字就能用了:
$ python main.py 12 榆树街的灯
这一页的例子都是各跑各的,导入不了你自己的文件;这个请在自己电脑上试。文件名别和标准模块重名(random.py、math.py):Python 会导入你的文件,而不是真正的那个模块。
if __name__ == "__main__"
每个模块都有一个变量叫 __name__。在你运行的那个文件里,它是 "__main__";在被导入的文件里,它是模块名,比如 "lamps"。这样一个文件就能做到:直接运行时做一件事,被导入时做另一件事。
1def cost(count):2 return count * 43 4def main():5 print(f"测试 cost:{cost(3)}")6 7print(__name__)8if __name__ == "__main__":9 main()
__main__ 测试 cost:12
直接运行这个文件,main() 就会跑。要是 main.py 用 import 导入它,__name__ 就是它的模块名,if 不成立,只定义了几个函数,不会显示测试结果。所以 if __name__ == "__main__": 下面放的,是只有这个文件自己当程序跑时才该跑的代码。
安装第三方包
标准库以外,Python 包索引(PyPI)上还有成千上万个别人写的包。在自己电脑上,用 pip 安装一个,在终端里敲,不是在 Python 里:
$ pip install requests Successfully installed requests
装好以后,import requests 就和别的模块一样用。有的系统上叫 pip3,或者写成 python -m pip。这里的浏览器例子装不了包;这门课用到的都在标准库里。
练一练
写好代码,点检查。提示随便看,实在想不出来再看答案。
平均数和中位数
✓用 statistics 模块,先显示灯亮的小时数的平均数,再显示中位数。
8 7
1hours = [6, 9, 7, 12, 6]前两名
✓用 from ... import 导入 Counter,数一数送来的货,显示最多的两种和它们的次数。
[('矿石', 3), ('灯油', 2)]1deliveries = ["灯油", "矿石", "灯芯", "矿石", "灯油", "矿石", "玻璃"]缺了哪些字母
✓按字母表顺序,把 sign 里没出现的字母连成一个词显示出来。用 string.ascii_lowercase。
dg
1sign = "the quick brown fox jumps over the lazy cat"这一课学会了
import 模块加载一个模块;用点拿里面的名字,比如math.sqrt。from 模块 import 名字只拿进这一个名字;as给模块或名字改名。- 标准库里有
random、statistics、collections、string、time这些模块;dir()、help()和 docs.python.org 能看里面有什么。 - 任何
.py文件都是模块,用名字就能导入;if __name__ == "__main__":下面的代码只在直接运行这个文件时才跑。 - 在终端里
pip install 名字,从 PyPI 安装包。