Kodewick
第 22 课,共 31 课目录

模块和导入

第 22 课,共 31 课 · 第 4 部分 · 代码和数据 · 约 20 分钟

模块就是一个装着 Python 代码、能给别的程序用的文件。Python 自带几百个,合起来叫标准库:算数学、处理日期、读写文件、随机数……早就有人写好、测好了。第 3 课已经见过一个:

main.py
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 算一组数常用的几种平均:

main.py
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 给模块或名字起一个更短、更清楚的名字。

main.py
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 mathmath.sqrt(9)
from math import sqrtsqrt(9)
import statistics as statsstats.mean(...)
from math import *math 里所有的名字,不用前缀;最好别用,看不出一个名字是从哪来的
先猜一猜

会怎么样?

1import math2 3print(math.ceil(2.5))4print(ceil(4.2))

几个好用的模块

模块干什么用例子
random随机数、随机挑random.randint(1, 6)
statistics平均数和离散程度statistics.median(xs)
collections更多容器:Counter、defaultdict、deque、namedtupleCounter(words)
string现成的字母、数字、标点字符串string.digits
time时钟,还有等一会儿time.sleep(1)
math开平方、向上向下取整、圆周率math.floor(2.7)

random 每次运行挑出来的都不一样,所以这里只检查结果是什么样的。多运行几次:背后的数在变,显示的结果不变。

main.py
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 里的容器,计数、分组的时候能省不少事:

main.py
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:

main.py
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)从一个文件导入另一个。比如你电脑上的同一个文件夹里有这两个文件:

lamps.py
1PRICE = 42 3def cost(count):4    return count * PRICE5 6def label(street):7    return street + "的灯"
main.py
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"。这样一个文件就能做到:直接运行时做一件事,被导入时做另一件事。

main.py
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。这里的浏览器例子装不了包;这门课用到的都在标准库里。

练一练

写好代码,点检查。提示随便看,实在想不出来再看答案。

练习 1

平均数和中位数

用 statistics 模块,先显示灯亮的小时数的平均数,再显示中位数。

要显示
8
7
exercise1.py
1hours = [6, 9, 7, 12, 6]
输出
点「运行」或按 Ctrl+Enter
练习 2

前两名

用 from ... import 导入 Counter,数一数送来的货,显示最多的两种和它们的次数。

要显示
[('矿石', 3), ('灯油', 2)]
exercise2.py
1deliveries = ["灯油", "矿石", "灯芯", "矿石", "灯油", "矿石", "玻璃"]
输出
点「运行」或按 Ctrl+Enter
练习 3

缺了哪些字母

按字母表顺序,把 sign 里没出现的字母连成一个词显示出来。用 string.ascii_lowercase。

要显示
dg
exercise3.py
1sign = "the quick brown fox jumps over the lazy cat"
输出
点「运行」或按 Ctrl+Enter

这一课学会了

  • import 模块 加载一个模块;用点拿里面的名字,比如 math.sqrt。
  • from 模块 import 名字 只拿进这一个名字;as 给模块或名字改名。
  • 标准库里有 random、statistics、collections、string、time 这些模块;dir()、help() 和 docs.python.org 能看里面有什么。
  • 任何 .py 文件都是模块,用名字就能导入;if __name__ == "__main__": 下面的代码只在直接运行这个文件时才跑。
  • 在终端里 pip install 名字,从 PyPI 安装包。