术语表规范同一术语只在首现单元收录后续单元写「见单元 N 术语表」正文与代码里出现的新写法必须在首现单元有词条。三列固定术语 / 一句话解释 / 首次出现。维护方式每单元写完把该单元术语表追加入本表。排序按单元号不是按拼音——本表从单元 00 顺着往下排方便逐单元核对有没有漏并。「首次出现」栏的语义正文里第一次出现该词的位置。若某个词在更早单元的正文里就被用过、但当时没建词条栏里写「单元 N正文首见 单元 M」例如「幂等」。术语一句话解释首次出现解释器interpreter读你的.py文件并执行它的程序python命令启动的就是它单元 00 §二教材纠正表本专栏的固定产出三列记录「书里这么写 / 现在要这么写 / 依据」单元 00 §二脚本script一个直接运行、不供别人导入的.py文件单元 00 §二依赖dependency你的代码运行时要用的别人写的库单元 00 §二包package一组模块加一个声明文件能被pip install安装单元 00 §四形参 / 实参parameter / argument定义时写在括号里的名字是形参调用时实际传进去的值是实参单元 03PATH环境变量是一串目录你敲python3时系统按这个顺序去找同名程序找到第一个就用它单元 01pipPython 的官方包安装器本单元要求一律用python -m pip调用让它绑定到你指定的解释器单元 01站点包目录site-packages环境里存放第三方库的地方「装到别的解释器去了」指的就是装进了另一个环境的这个目录单元 01激活activate把环境的bin目录临时插到PATH最前面的脚本只影响当前这个终端窗口不激活也能用完整路径跑单元 01sys.prefix/sys.base_prefix前者是当前解释器所属的环境路径后者是造出它的基础解释器路径两者不等就说明在虚拟环境里单元 01pyvenv.cfg环境根目录下的配置文件记着基础解释器的位置与include-system-site-packages是否继承系统包单元 01wheel.whl预先构建好的二进制包格式pip 优先装 wheel找不到才去下载源码包现场编译单元 01扩展VS Code extension给编辑器加装的功能模块Python 扩展负责运行代码与选择解释器装的时候认准 Microsoft 那个单元 01uvAstral 写的环境与依赖管理工具Rust 实现默认按项目建.venv不读 pip 的配置文件单元 01外部管理环境EXTERNALLY-MANAGED发行版打在系统 Python 目录里的标记文件装了它的解释器不接受工具往全局装包只能走虚拟环境单元 01变量variable给一个值起的名字名字指向值值本身有类型单元 02动态类型dynamic typing类型跟着值走而不是跟着名字走同一个名字可以先后指向不同类型的值单元 02字符串str一串 Unicode 字符不可变删字符、改大小写都是返回新字符串单元 02转义字符escape character反斜杠加字符表示一个看不见或不好打的字符如\t、\n、\u3000单元 02repr()给人和调试看的字符串表示带引号、控制字符转义f-string 里写!r就是调它单元 02f-string引号前加f的字符串字面量用{...}插值可带!r与:格式说明单元 02类型转换type conversion用int()/float()之类把一种类型的值换成另一种失败了会抛异常单元 02异常exception出错时中断正常流程的对象ValueError是值不合适TypeError是类型不合适单元 02Unicode 归一化NFKC把兼容等价的字符折成常规形式全角折半角、①折成1有损不可逆单元 02不可见字符BOM / 零宽字符占了码位却看不见的字符UFEFF、U200B 等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数据类dataclassdataclass装饰的类字段名写在类里自动生成__init__与__repr__配frozenTrue不可改、slotsTrue省内存单元 04 §二 准则 4可迭代对象iterable能一次交出一个成员的东西列表、元组、字典、文件对象都算for吃的就是它单元 04 §三 配方 1推导式comprehension用一个表达式造出列表或字典的写法形状是[f(x) for x in it if cond]单元 04 §三 配方 1类class你自己定义的一种类型用class声明Think Python 把它叫「程序员自定义类型」单元 05实例instance按类造出来的具体对象造一个实例这个动作叫实例化instantiationNoteReader(BAD)造出来的那一个就是实例单元 05属性attribute挂在实例上、用点号访问的变量例如reader.records单元 05方法method定义在类里的函数第一个参数固定是self单元 05self方法里的「这个实例」由 Python 自动传不用你写在实参里单元 05继承inheritance在已有类上定义修改版本篇用它让BadLineError属于NoteError单元 05上下文管理器context manager能配with用的对象进入时调__enter__离开时调__exit__open()的返回值就是一个单元 05__repr__决定「官方字符串表示」的特殊方法调试输出走它要求信息足、不含糊单元 05finallytry语句的收尾分支无论成功还是抛出异常都会执行单元 05单元测试unit test验证函数行为中某一个具体方面的测试一个函数一条名字写成一句人话单元 06断言assertion测试里那句「我认为这里应该是这样」的判断句用标准的assert写失败时 pytest 会补出中间值单元 06反例测试故意跑红拿一份故意改坏的实现喂同一批断言用来看测试到底抓不抓得住 bug本篇放在code/u06_assertions_broken.py并用broken标记排除在默认运行之外单元 06测试用例test case一组单元测试的集合合起来证明一个函数在预期范围内都对单元 06断言重写assertion rewritingpytest 在导入测试模块时改写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%单元 06Big 4Head First Python对list/tuple/dict/set四种内置容器的叫法本篇用「要不要唯一、要不要计数、要不要顺序」三句判据在它们之间选单元 07集合set只存不重复元素的容器迭代顺序不保证转换一次就把重复项去掉单元 07list-set-list 三连教材 ch 5 的叫法set去重、再转回list本篇在中间补一步sorted()让顺序可复现单元 07Countercollections里的计数字典取值默认是 0给它赋一个新键会真的写进去那不是查询单元 07most_common(n)Counter的方法按次数降序取前 n 项次数相同的按首次出现的先后排列单元 07排序稳定性stable sort键值相同的元素保持原有先后sorted是稳定的reverseTrue不会把并列项倒过来单元 07显示宽度East Asian Width一个字符在等宽终端里占几列汉字占 2 列len()数的是字符个数不是列数单元 07文本条形图text bar chart用 f-string 加重复字符拼出的条形图不依赖绘图库只在等宽字体下对齐单元 07两列 CSV可画图数据name,count这种两列表格文本Excel、gnuplot、matplotlib 都认这个形状单元 07utf-8-sig读文件时用的编码名与utf-8行为相同另外顺手丢掉文件开头的 BOM单元 07条目entry名单里一个候选名字先定「什么算一个条目」再谈怎么数单元 08模块module一个.py文件别人用import取用里面的名字u08_roster.py被测试当模块导入单元 08并列tie排序键相同的情况本篇特指次数相同的几个名字谁排前面单元 08退出码exit code程序结束时交给 shell 的整数0 通常表示成功、非 0 表示出了状况单元 08项目单元从单元 09 起每篇长出一个能跑的工具上一个版本的代码是下一个版本的起点单元 09dry-run只把要做的事打成清单、不动磁盘的运行方式本篇里它是默认值单元 09正则表达式regular expression描述一类文本模式的字符串re模块用它做查找与替换单元 09原始字符串raw string前缀r的字符串字面量反斜杠不被 Python 先转义一层单元 09路径对象Pathpathlib里代表一个路径的对象不可变、可哈希/用来拼路径单元 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属性抑制defaultargparse.SUPPRESS让「命令行里没给这个选项」等同于「不要往Namespace上写这个属性」因此不覆盖上一级解析器读到的值代价是取值要getattr兜底单元 10 §二 准则 4父解析器parents一个add_helpFalse的解析器专门装多个子命令共用的选项再通过parents[...]复制进各级解析器单元 10 §三 配方 1if __name__ __main__守卫判断这个文件是「被当脚本跑」还是「被当模块导入」的那一句有了它导入模块不会执行main()单元 10 §三 配方 5入口点entry point程序开始执行的那一句v0.2 是raise SystemExit(main())收成包之后换成[project.scripts]单元 10 §三 配方 5Figure / Axesmatplotlib 面向对象接口里的两块Figure 是画布Axes 是画布上的一个坐标系单元 12 §三 配方 3位图与矢量图raster / vector位图PNG由像素构成放大就糊矢量图SVG / PDF由图形指令构成放大不糊单元 12 §二 准则 3字形轮廓glyph outline把每个字的字形转成矢量路径存进文件svg.fonttypepath的产物到哪台机器都不缺字体但文字不可选中单元 12 §二 准则 3字体族font family一个字体名字例如Noto Sans CJK SC程序里能设的、能探测的都是族名不是字体文件路径单元 12 §二 准则 1字体回退font fallback首选字体缺某个字形时自动到链上的下一个字体里找单元 12 §三 配方 2缺字警告missing glyph warning画不出某个字符时打的UserWarning: Glyph ... missing from font(s) ...「一条都没有」是中文真画出来了的可验证证据单元 12 §三 配方 1dpidots per inch每英寸多少个像素像素数约等于 figsize 乘 dpi调大它只改清晰度、不改版式单元 12 §三 配方 4bbox_inchestightsavefig的参数按实际画出来的内容裁剪代价是输出尺寸不再等于 figsize 乘 dpi可能大也可能小单元 12 §三 配方 4交互图interactive chart能在浏览器里悬停看数值、框选缩放的图plotly 是这一路代价是多一个依赖和文件体积单元 12 §三 配方 5序列化serialization把内存里的数据结构变成一段可存可传的文本CSV / JSON / XML 都是序列化格式单元 11 §一工作表worksheetxlsx 里的一张表一个工作簿workbook可以有多个用名字或 1 起编号选单元 11 §4.2单元格cell工作表里行与列交叉的那一格用A1这样的坐标寻址单元 11 §一共享字符串表shared stringsxlsx 内部把重复出现的字符串存一张表、单元格里只放下标标准库后端要自己解这层单元 11 §二 准则 3可选后端optional backend同一个格式的两条实现装了第三方库就用库没装就退回标准库报告里要写清这次用了谁单元 11 §二 准则 3PDF 文本层text layerPDF 里实际存文字的那一层扫描件只有图片、没有它所以抽出来是空的单元 11 §二 准则 2内容流content streamPDF 里描述「这一页画什么」的字节流文本算符就藏在里面本篇用zlib解开它再拼字符串单元 11 §一CSV 方言dialect一套 CSV 的格式参数分隔符、引号、换行Sniffer是从样本里猜出一套单元 11 §三 配方 1UPSERT「撞主键就更新、没撞就插入」的一句 SQL靠ON CONFLICT ... DO UPDATESQLite 3.24.0 起有单元 11 §二 准则 4类型亲和性type affinitySQLite 列的「推荐类型」能转就自动转转不了也照样存不报错单元 11 §三 配方 5重构refactoring在不改变外部可见行为的前提下调整代码结构本篇的验收标准是「输出逐字节不变」与「代码更好看」无关单元 13 §一特征测试characterization test先录下旧代码的当前行为、再要求新代码重放同一行为的测试期望值来自旧代码的输出单元 13 §二 准则 1对拍把同一份输入分别交给新旧两份实现比对输出是否相同「逐字节对拍」连全角空格与行尾都不放过单元 13 §二 准则 1裁判脚本本篇指没被重构过的code/u09_organize.py函数级对拍按路径导入它端到端对拍用子进程跑它单元 13 §二 准则 1可观测输出observable output一次运行在外面能看见的东西stdout 每一行、stderr、退出码、落盘结果、异常类型与文字单元 13 §二 准则 3src布局src layout把可导入的源码放进src/包名/子目录的布局装了才 import 得到避免「本地能跑」掩盖打包漏文件单元 13 §二 准则 4可编辑安装editable installpip install -e装出来的包指向源码目录改代码不用重装datanote命令就这样指向仓库里的src/单元 13 §一包入口点entry pointpyproject.toml里[project.scripts]的一行「命令名 模块:函数」pip 据此生成可执行脚本函数返回值就是退出码单元 13 §二 准则 4PYTHONPATH环境变量一串目录解释器启动时把它们插进sys.path用来在没装包时 import 到源码树单元 13 §二 准则 1桥接测试bridge test放在code/tests/里、把子目录中的包接进全专栏验证入口的测试它只留最关键的几条「装得上」由包内测试在独立环境里证单元 13 §一线性搜索linear search从头逐个元素比过去、命中即返回不要求有序代价 O(n)单元 14 §一二分查找binary search每轮把待查区间砍成一半只比较中间那个元素要求有序代价 O(log n)单元 14 §一插入点insertion pointbisect_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 §一