术语表规范:同一术语只在首现单元收录,后续单元写「见单元 N 术语表」;正文与代码里出现的新写法必须在首现单元有词条。三列固定:术语 / 一句话解释 / 首次出现。
维护方式:每单元写完,把该单元术语表追加入本表。排序按单元号(不是按拼音——本表从单元 00 顺着往下排,方便逐单元核对有没有漏并)。
「首次出现」栏的语义:正文里第一次出现该词的位置。若某个词在更早单元的正文里就被用过、但当时没建词条,栏里写「单元 N(正文首见 单元 M)」,例如「幂等」。
| 术语 | 一句话解释 | 首次出现 |
|---|---|---|
| 解释器(interpreter) | 读你的.py文件并执行它的程序;python命令启动的就是它 | 单元 00 §二 |
| 教材纠正表 | 本专栏的固定产出:三列记录「书里这么写 / 现在要这么写 / 依据」 | 单元 00 §二 |
| 脚本(script) | 一个直接运行、不供别人导入的.py文件 | 单元 00 §二 |
| 依赖(dependency) | 你的代码运行时要用的别人写的库 | 单元 00 §二 |
| 包(package) | 一组模块加一个声明文件,能被pip install安装 | 单元 00 §四 |
| 形参 / 实参(parameter / argument) | 定义时写在括号里的名字是形参,调用时实际传进去的值是实参 | 单元 03 |
| PATH | 环境变量,是一串目录;你敲python3时系统按这个顺序去找同名程序,找到第一个就用它 | 单元 01 |
pip | Python 的官方包安装器;本单元要求一律用python -m pip调用,让它绑定到你指定的解释器 | 单元 01 |
站点包目录(site-packages) | 环境里存放第三方库的地方;「装到别的解释器去了」指的就是装进了另一个环境的这个目录 | 单元 01 |
| 激活(activate) | 把环境的bin目录临时插到PATH最前面的脚本;只影响当前这个终端窗口,不激活也能用完整路径跑 | 单元 01 |
sys.prefix/sys.base_prefix | 前者是当前解释器所属的环境路径,后者是造出它的基础解释器路径;两者不等就说明在虚拟环境里 | 单元 01 |
pyvenv.cfg | 环境根目录下的配置文件,记着基础解释器的位置与include-system-site-packages是否继承系统包 | 单元 01 |
wheel(.whl) | 预先构建好的二进制包格式;pip 优先装 wheel,找不到才去下载源码包现场编译 | 单元 01 |
| 扩展(VS Code extension) | 给编辑器加装的功能模块;Python 扩展负责运行代码与选择解释器,装的时候认准 Microsoft 那个 | 单元 01 |
uv | Astral 写的环境与依赖管理工具(Rust 实现);默认按项目建.venv,不读 pip 的配置文件 | 单元 01 |
外部管理环境(EXTERNALLY-MANAGED) | 发行版打在系统 Python 目录里的标记文件;装了它的解释器不接受工具往全局装包,只能走虚拟环境 | 单元 01 |
| 变量(variable) | 给一个值起的名字;名字指向值,值本身有类型 | 单元 02 |
| 动态类型(dynamic typing) | 类型跟着值走而不是跟着名字走,同一个名字可以先后指向不同类型的值 | 单元 02 |
字符串(str) | 一串 Unicode 字符,不可变;删字符、改大小写都是返回新字符串 | 单元 02 |
| 转义字符(escape character) | 反斜杠加字符表示一个看不见或不好打的字符,如\t、\n、\u3000 | 单元 02 |
repr() | 给人和调试看的字符串表示:带引号、控制字符转义;f-string 里写!r就是调它 | 单元 02 |
| f-string | 引号前加f的字符串字面量,用{...}插值,可带!r与:格式说明 | 单元 02 |
| 类型转换(type conversion) | 用int()/float()之类把一种类型的值换成另一种;失败了会抛异常 | 单元 02 |
| 异常(exception) | 出错时中断正常流程的对象;ValueError是值不合适,TypeError是类型不合适 | 单元 02 |
| Unicode 归一化(NFKC) | 把兼容等价的字符折成常规形式:全角折半角、①折成1;有损,不可逆 | 单元 02 |
| 不可见字符(BOM / 零宽字符) | 占了码位却看不见的字符,U+FEFF、U+200B 等;isspace()不认它们,strip()删不掉 | 单元 02 |
| 控制流(control flow) | 决定「下一句执行哪一句」的语句:条件、循环、提前返回都算 | 单元 03 |
| 迭代(iteration) | 对一组东西里的每一项重复执行同一段代码,for与while是两种写法 | 单元 03 |
| 函数(function) | 有名字、能收参数、能返回值的代码块,用def定义 | 单元 03 |
| 接口与实现(interface / implementation) | 接口是「别人怎么用它」(名字、参数、承诺返回什么),实现是「你打算怎么做」 | 单元 03 |
| 增量式开发(incremental development) | 一次只加一小段代码、改一点就验一次,出错时问题就在刚写的那几行里 | 单元 03 |
| 返回值(return value) | 函数交给调用方的那个值;没有return的函数返回None | 单元 03 |
| 纯函数(pure function) | 只靠参数算出结果,不打印、不改外部状态,同样输入永远同样输出 | 单元 03 |
| 守卫子句(guard clause) | 函数开头那几行「命中就立刻 return」的检查,用它把嵌套压平 | 单元 03 |
| 作用域(scope) | 一个名字在哪段代码里可见;函数体会新开一张局部符号表 | 单元 03 |
列表(list) | 有序、可重复、按下标取元素的一组值;元素是「同类的东西」 | 单元 04 §一 |
元组(tuple) | 一串用逗号分开、不可改的值;元素是「一条记录的各个字段」,位置有意义 | 单元 04 §一 |
字典(dict) | 键值对的映射,键唯一且必须可哈希;按插入顺序迭代 | 单元 04 §一 |
| 嵌套结构(nested structure) | 容器里再放容器,如字典列表、字典套字典、列表字典;取字段的写法由嵌套形状决定 | 单元 04 §一 |
| 列表字典(columnar layout) | 每个字段一个列表、记录对齐成几列;整列计算快、省内存,但按名字取一条要扫一遍,列对齐要自己保证 | 单元 04 §一 |
| 记录(record) | 一组有名字的字段的打包;本篇用字典、元组、数据类三种东西装它 | 单元 04 §二 准则 1 |
| 可哈希(hashable) | 哈希值终生不变、可比较的值,能当字典的键;列表与字典不可哈希,元组要看元素 | 单元 04 §二 准则 2 |
数据类(dataclass) | @dataclass装饰的类,字段名写在类里,自动生成__init__与__repr__;配frozen=True不可改、slots=True省内存 | 单元 04 §二 准则 4 |
| 可迭代对象(iterable) | 能一次交出一个成员的东西,列表、元组、字典、文件对象都算;for吃的就是它 | 单元 04 §三 配方 1 |
| 推导式(comprehension) | 用一个表达式造出列表或字典的写法,形状是[f(x) for x in it if cond] | 单元 04 §三 配方 1 |
| 类(class) | 你自己定义的一种类型,用class声明;Think Python 把它叫「程序员自定义类型」 | 单元 05 |
| 实例(instance) | 按类造出来的具体对象;造一个实例这个动作叫实例化(instantiation),NoteReader(BAD)造出来的那一个就是实例 | 单元 05 |
| 属性(attribute) | 挂在实例上、用点号访问的变量,例如reader.records | 单元 05 |
| 方法(method) | 定义在类里的函数,第一个参数固定是self | 单元 05 |
self | 方法里的「这个实例」;由 Python 自动传,不用你写在实参里 | 单元 05 |
| 继承(inheritance) | 在已有类上定义修改版;本篇用它让BadLineError属于NoteError | 单元 05 |
| 上下文管理器(context manager) | 能配with用的对象;进入时调__enter__,离开时调__exit__,open()的返回值就是一个 | 单元 05 |
__repr__ | 决定「官方字符串表示」的特殊方法,调试输出走它;要求信息足、不含糊 | 单元 05 |
finally | try语句的收尾分支,无论成功还是抛出异常都会执行 | 单元 05 |
| 单元测试(unit test) | 验证函数行为中某一个具体方面的测试,一个函数一条,名字写成一句人话 | 单元 06 |
| 断言(assertion) | 测试里那句「我认为这里应该是这样」的判断句,用标准的assert写,失败时 pytest 会补出中间值 | 单元 06 |
| 反例测试(故意跑红) | 拿一份故意改坏的实现喂同一批断言,用来看测试到底抓不抓得住 bug;本篇放在code/u06_assertions_broken.py,并用broken标记排除在默认运行之外 | 单元 06 |
| 测试用例(test case) | 一组单元测试的集合,合起来证明一个函数在预期范围内都对 | 单元 06 |
| 断言重写(assertion rewriting) | pytest 在导入测试模块时改写assert语句,让失败报告带出中间值;它只作用于被收集到的测试模块 | 单元 06 |
| 参数化(parametrization) | 用@pytest.mark.parametrize把一张参数表展开成多条独立用例,红的时候只标出坏的那几行 | 单元 06 |
| 夹具(fixture) | 测试运行前把「世界」准备好并递进用例的东西;本篇用的是 pytest 内置的tmp_path,每个用例一个专属目录 | 单元 06 |
| 回归(regression) | 已经对的行为被后来的改动弄坏;回归测试是把旧契约钉住的那些用例,tests/test_u06_regression.py就是干这个的 | 单元 06 |
| 覆盖率(coverage) | 代码里有多少行被执行过;本机没装pytest-cov,本篇用标准库trace量(实测演示脚本只覆盖u06_assertions.py的 65.5%) | 单元 06 |
| Big 4 | Head First Python对list/tuple/dict/set四种内置容器的叫法;本篇用「要不要唯一、要不要计数、要不要顺序」三句判据在它们之间选 | 单元 07 |
集合(set) | 只存不重复元素的容器;迭代顺序不保证,转换一次就把重复项去掉 | 单元 07 |
| list-set-list 三连 | 教材 ch 5 的叫法:set去重、再转回list;本篇在中间补一步sorted()让顺序可复现 | 单元 07 |
Counter | collections里的计数字典,取值默认是 0;给它赋一个新键会真的写进去,那不是查询 | 单元 07 |
most_common(n) | Counter的方法,按次数降序取前 n 项;次数相同的按首次出现的先后排列 | 单元 07 |
| 排序稳定性(stable sort) | 键值相同的元素保持原有先后;sorted是稳定的,reverse=True不会把并列项倒过来 | 单元 07 |
| 显示宽度(East Asian Width) | 一个字符在等宽终端里占几列;汉字占 2 列,len()数的是字符个数,不是列数 | 单元 07 |
| 文本条形图(text bar chart) | 用 f-string 加重复字符拼出的条形图;不依赖绘图库,只在等宽字体下对齐 | 单元 07 |
| 两列 CSV(可画图数据) | name,count这种两列表格文本;Excel、gnuplot、matplotlib 都认这个形状 | 单元 07 |
utf-8-sig | 读文件时用的编码名;与utf-8行为相同,另外顺手丢掉文件开头的 BOM | 单元 07 |
| 条目(entry) | 名单里一个候选名字;先定「什么算一个条目」,再谈怎么数 | 单元 08 |
| 模块(module) | 一个.py文件,别人用import取用里面的名字;u08_roster.py被测试当模块导入 | 单元 08 |
| 并列(tie) | 排序键相同的情况;本篇特指次数相同的几个名字谁排前面 | 单元 08 |
| 退出码(exit code) | 程序结束时交给 shell 的整数,0 通常表示成功、非 0 表示出了状况 | 单元 08 |
| 项目单元 | 从单元 09 起每篇长出一个能跑的工具,上一个版本的代码是下一个版本的起点 | 单元 09 |
| dry-run | 只把要做的事打成清单、不动磁盘的运行方式;本篇里它是默认值 | 单元 09 |
| 正则表达式(regular expression) | 描述一类文本模式的字符串,re模块用它做查找与替换 | 单元 09 |
| 原始字符串(raw string) | 前缀r的字符串字面量,反斜杠不被 Python 先转义一层 | 单元 09 |
路径对象(Path) | pathlib里代表一个路径的对象,不可变、可哈希,/用来拼路径 | 单元 09 |
| 规范化(normalize) | 把一批形态各异的名字按固定规则整成同一种写法 | 单元 09 |
| 幂等(idempotent) | 同一个操作做一遍和做两遍结果一样;整理工具能反复跑的前提(词条收在单元 09,该词在单元 06 正文已先出现) | 单元 09(正文首见 单元 06) |
| 归档目录 | 工具按类型建出来的八个目标目录(图片 / 文档 / 表格 / 音频 / 视频 / 压缩包 / 代码 / 其他),它们是保留名 | 单元 09 |
| 指纹(fingerprint) | 本篇指「文件大小 + 首尾各 4 KB 内容的 SHA-256 摘要」;这里的哈希是加密哈希,与单元 04 里字典用的整数哈希不是一回事 | 单元 09 |
| 误判边界(假阳性) | 抽样指纹说「可能相同」而实际不同的情形;本篇给出它成立的四个条件 | 单元 09 |
| 命令行界面(CLI) | 靠敲命令和选项来用的程序界面,与图形界面相对;datanote就是一个 | 单元 10 §一 |
| 子命令(subcommand) | 一个程序里的若干个动词,如datanote organize与datanote report;每个子命令有自己的选项表 | 单元 10 §二 准则 1 |
| 标准输出与标准错误(stdout / stderr) | 进程的两个输出流;约定结果走 stdout、过程日志走 stderr,所以重定向 stdout 拿到的文件里没有日志 | 单元 10 §二 准则 2 |
| 日志等级(log level) | 给日志消息分重要程度的档位,logging有 DEBUG / INFO / WARNING / ERROR / CRITICAL 五档;等级是装在 logger 上的阈值 | 单元 10 §二 准则 2 |
| 退出码约定(五分类) | 定下来的五个码:0 成功 / 1 运行期错 / 2 参数错 / 3 部分成功 / 4 没有可做的事;调用方按码分流,不 grep 输出文本 | 单元 10 §二 准则 3 |
属性抑制(default=argparse.SUPPRESS) | 让「命令行里没给这个选项」等同于「不要往Namespace上写这个属性」,因此不覆盖上一级解析器读到的值;代价是取值要getattr兜底 | 单元 10 §二 准则 4 |
父解析器(parents=) | 一个add_help=False的解析器,专门装多个子命令共用的选项,再通过parents=[...]复制进各级解析器 | 单元 10 §三 配方 1 |
if __name__ == "__main__"守卫 | 判断这个文件是「被当脚本跑」还是「被当模块导入」的那一句;有了它,导入模块不会执行main() | 单元 10 §三 配方 5 |
| 入口点(entry point) | 程序开始执行的那一句;v0.2 是raise SystemExit(main()),收成包之后换成[project.scripts] | 单元 10 §三 配方 5 |
| Figure / Axes | matplotlib 面向对象接口里的两块:Figure 是画布,Axes 是画布上的一个坐标系 | 单元 12 §三 配方 3 |
| 位图与矢量图(raster / vector) | 位图(PNG)由像素构成,放大就糊;矢量图(SVG / PDF)由图形指令构成,放大不糊 | 单元 12 §二 准则 3 |
| 字形轮廓(glyph outline) | 把每个字的字形转成矢量路径存进文件;svg.fonttype='path'的产物,到哪台机器都不缺字体,但文字不可选中 | 单元 12 §二 准则 3 |
| 字体族(font family) | 一个字体名字,例如Noto Sans CJK SC;程序里能设的、能探测的都是族名,不是字体文件路径 | 单元 12 §二 准则 1 |
| 字体回退(font fallback) | 首选字体缺某个字形时,自动到链上的下一个字体里找 | 单元 12 §三 配方 2 |
| 缺字警告(missing glyph warning) | 画不出某个字符时打的UserWarning: Glyph ... missing from font(s) ...;「一条都没有」是中文真画出来了的可验证证据 | 单元 12 §三 配方 1 |
| dpi(dots per inch) | 每英寸多少个像素;像素数约等于 figsize 乘 dpi,调大它只改清晰度、不改版式 | 单元 12 §三 配方 4 |
bbox_inches="tight" | savefig的参数,按实际画出来的内容裁剪;代价是输出尺寸不再等于 figsize 乘 dpi,可能大也可能小 | 单元 12 §三 配方 4 |
| 交互图(interactive chart) | 能在浏览器里悬停看数值、框选缩放的图;plotly 是这一路,代价是多一个依赖和文件体积 | 单元 12 §三 配方 5 |
| 序列化(serialization) | 把内存里的数据结构变成一段可存可传的文本;CSV / JSON / XML 都是序列化格式 | 单元 11 §一 |
| 工作表(worksheet) | xlsx 里的一张表;一个工作簿(workbook)可以有多个,用名字或 1 起编号选 | 单元 11 §4.2 |
| 单元格(cell) | 工作表里行与列交叉的那一格,用A1这样的坐标寻址 | 单元 11 §一 |
| 共享字符串表(shared strings) | xlsx 内部把重复出现的字符串存一张表、单元格里只放下标;标准库后端要自己解这层 | 单元 11 §二 准则 3 |
| 可选后端(optional backend) | 同一个格式的两条实现:装了第三方库就用库,没装就退回标准库,报告里要写清这次用了谁 | 单元 11 §二 准则 3 |
| PDF 文本层(text layer) | PDF 里实际存文字的那一层;扫描件只有图片、没有它,所以抽出来是空的 | 单元 11 §二 准则 2 |
| 内容流(content stream) | PDF 里描述「这一页画什么」的字节流,文本算符就藏在里面;本篇用zlib解开它再拼字符串 | 单元 11 §一 |
| CSV 方言(dialect) | 一套 CSV 的格式参数:分隔符、引号、换行;Sniffer是从样本里猜出一套 | 单元 11 §三 配方 1 |
| UPSERT | 「撞主键就更新、没撞就插入」的一句 SQL;靠ON CONFLICT ... DO UPDATE,SQLite 3.24.0 起有 | 单元 11 §二 准则 4 |
| 类型亲和性(type affinity) | SQLite 列的「推荐类型」:能转就自动转,转不了也照样存,不报错 | 单元 11 §三 配方 5 |
| 重构(refactoring) | 在不改变外部可见行为的前提下调整代码结构;本篇的验收标准是「输出逐字节不变」,与「代码更好看」无关 | 单元 13 §一 |
| 特征测试(characterization test) | 先录下旧代码的当前行为、再要求新代码重放同一行为的测试;期望值来自旧代码的输出 | 单元 13 §二 准则 1 |
| 对拍 | 把同一份输入分别交给新旧两份实现,比对输出是否相同;「逐字节对拍」连全角空格与行尾都不放过 | 单元 13 §二 准则 1 |
| 裁判脚本 | 本篇指没被重构过的code/u09_organize.py:函数级对拍按路径导入它,端到端对拍用子进程跑它 | 单元 13 §二 准则 1 |
| 可观测输出(observable output) | 一次运行在外面能看见的东西:stdout 每一行、stderr、退出码、落盘结果、异常类型与文字 | 单元 13 §二 准则 3 |
src布局(src layout) | 把可导入的源码放进src/<包名>/子目录的布局;装了才 import 得到,避免「本地能跑」掩盖打包漏文件 | 单元 13 §二 准则 4 |
| 可编辑安装(editable install) | pip install -e装出来的包指向源码目录,改代码不用重装;datanote命令就这样指向仓库里的src/ | 单元 13 §一 |
| 包入口点(entry point) | pyproject.toml里[project.scripts]的一行「命令名 = 模块:函数」;pip 据此生成可执行脚本,函数返回值就是退出码 | 单元 13 §二 准则 4 |
PYTHONPATH | 环境变量,一串目录;解释器启动时把它们插进sys.path,用来在没装包时 import 到源码树 | 单元 13 §二 准则 1 |
| 桥接测试(bridge test) | 放在code/tests/里、把子目录中的包接进全专栏验证入口的测试;它只留最关键的几条,「装得上」由包内测试在独立环境里证 | 单元 13 §一 |
| 线性搜索(linear search) | 从头逐个元素比过去、命中即返回;不要求有序,代价 O(n) | 单元 14 §一 |
| 二分查找(binary search) | 每轮把待查区间砍成一半,只比较中间那个元素;要求有序,代价 O(log n) | 单元 14 §一 |
| 插入点(insertion point) | bisect_left的返回值:第一个不小于目标值的位置;它永远是合法下标,所以看着像「找到了」 | 单元 14 §一 |
| 递归(recursion) | 函数在执行过程中调用自己;每种递归都要有一个不再调用的出口 | 单元 14 §二 准则 4 |
| 基线条件(base case) | 递归函数里那个不再发起递归调用的分支;少了它,程序会一直往下递归 | 单元 14 §二 准则 4 |
| 不变量(invariant) | 在一段代码的每次执行前后都应当成立的性质;本篇用它把「返回值一定合法」写成一行断言 | 单元 14 §一 |
| 复杂度(complexity) | 用输入规模 n 描述工作量增长的写法:O(n) 随 n 线性涨,O(log n) 每翻一倍规模只多一步 | 单元 14 §一 |
| 拐点(crossover) | 两条耗时曲线交叉的规模;过了它,原先较慢的一版开始更快。注意:它是采样式测量,必须连采样次数一起给(单元 14 实测两侧都在 24–48 与 96–128 之间跳) | 单元 14 §三 配方 4 |
| 参照实现(reference implementation) | 不作为交付方案、只用来给其他实现当对比基准的那一份;本篇指list.index那一版 | 单元 14 §一 |