2022-回放-02:面向对象概念引入、列表推导式与第一次作业 ROT13(第二次直播回放)¶
内容梗概¶
这是第二次直播回放课(约 1 小时 56 分钟)。开头解决了上次遗留的 dlib 安装问题(装 Visual C++ 编译工具,或直接用预编译的 .whl 文件),并补充了"语言绑定"概念。随后进入正式内容:以"万物皆对象"为线索引入面向对象、类与实例化的概念,讲解如何查 Python 官方文档(并推荐离线文档工具 Zeal/Dash),演示字符串/列表的常用方法与列表推导式。后半节课围绕第一次作业展开:先画流程图拆解任务,再逐行讲解示例代码和 ROT13 算法的实现思路,最后布置作业。课上还补充了 VS Code 报波浪线(Lint 环境不匹配)的原因。
知识点详解¶
dlib 安装问题的解决方案(约 00:00–04:50)¶
- 方案一:安装 Visual Studio 的 C++ 编译工具,在"单个组件"里搜索勾选 CMake 相关组件("用于 CMake 和 Linux 的 Visual C++ 工具",约 5GB)。dlib 原生在 Linux 下运行较好,在 Windows 上需要 CMake 编译,装好后
pip install dlib不再报错。 - 方案二(推荐省事):直接下载别人编译好的
.whl文件(注意对应 Python 版本,如 cp310 对应 3.10),cd到下载目录后pip install 文件名.whl。pip install后跟包名会去服务器下载,跟本地文件路径则直接安装本地包,无需再编译。 - 小结三个要点:Python 的包怎么装(pip);为什么要编译——dlib 是 C++ 写的,通过动态链接方式被加载,必须在目标平台编译;编译失败是因为缺 CMake 等编译工具。
- 额外知识——语言绑定(language binding):dlib、OpenCV、jieba(中文分词)等库不管本身用什么语言实现,都会提供不同语言的绑定(对应语言的 API),Python/Java/Go 等都能调用,不必关心其内部实现语言。
面向过程 vs 面向对象(约 08:30–14:40)¶
- 用"自动买菜程序"对比两种思路:
- 面向过程:按执行顺序思考(穿衣拿钱包 → 坐车去菜市场 → 依次买每样菜)。
- 面向对象:先梳理涉及哪些对象(钱包:有多少钱/能装多少钱等属性,能被打开等操作;菜贩子:卖什么菜的属性),再考虑对象间交互。
- 两者只是侧重点不同:一个侧重完成任务的过程,一个侧重参与任务的真实对象的特征(属性)和行为(方法)。属性即对象里的变量,方法即对象里的函数。
Python 万物皆对象、类与实例化(约 14:40–26:30)¶
- Python 从设计之初就是面向对象语言,所有基础类型(字符串、数字等)本质上都是对象,都有属性和可调用的方法。这与 C 语言的用法差异很大,而在 Python 里非常常见,作业中会大量使用。
int本身就是一个 class(文档中写作class int)。字符串str有大量方法:capitalize(首字母大写)、count(统计子串出现次数)、find(查子串位置)等。老师现场演示误把isinstance当成 int 的方法"翻车",随后澄清:isinstance(对象, 类型)是内置函数,判断某变量是否属于某类型。- 类(class)与实例化(instantiation):类是统称/图纸(如
person类定义了 name、age、gender 等特征),本身不是可操作的实体;根据类创建出可操作的对象的过程叫实例化,创建出的对象叫该类的一个实例(如a.name = "安静",a是 person 类的一个实例/对象)。 type(x)函数返回变量的类型,显示为<class 'str'>等。- 类型转换函数
int(x, base=10)实质是 int 类的实例化(构造)函数:base表示**传入字符串本身是什么进制**(不是"转成几进制")。如int("110011010", 2)把二进制字符串转成十进制数;int("18", 2)报错,因为 "18" 不是合法二进制串。
查文档与离线文档工具(约 31:00–34:30)¶
- 鼓励大家自己查 python.org 官方文档(老师上课时反复演示从首页进入文档搜索的过程)。
- 推荐离线文档软件:Windows/Linux 用 Zeal,macOS 用 Dash(开源免费,"offline documentation browser for software developers")。支持
python3:print这种"语言:关键词"检索,带源码示例;各主流语言(C、Java、JS、Go 等)的文档都有,按需缓存,占磁盘空间。
for 循环、range 与列表推导式(约 34:40–48:30)¶
range(n):生成从 0 到 n-1 的序列;for i in range(26):让 i 依次取 0–25。- 需求引出:作业要处理字母表,手打
ABCDEFG...Z26 个字母"过于朴实",程序员追求自动生成。 - 背景知识 ASCII 码:电脑只能存数字,ASCII 表建立数字与字符的对应。大写 A 对应十进制 65,A–Z 即 65+0 到 65+25。
ord(字符)把单个字符转成对应整数(ASCII 码),chr(整数)反过来转成字符。如ord('A')→ 65,chr(ord('A')+1)→ 'B'。- 朴素写法:循环里
number = 65 + i、char = chr(number)、result.append(char)(append在列表末尾追加元素)。 - 列表推导式:一句话生成整个列表——
b = [chr(65 + i) for i in range(26)],与上面循环完全等价,是本课重点强调的写法(作业会用到)。 - 列表转字符串:用字符串的
join方法——''.join(b)无缝拼接,','.join(b)以逗号分隔(典型场景:把全班名单列表拼成逗号分隔的串)。反过来c.split(',')把逗号分隔的字符串拆成列表。空字符串''仍是字符串类型,只是内容为空。
in 关键字(约 1:04:00–1:07:00)¶
in用于判断包含关系:if 'a' in '安静':判断子串是否在字符串中;'张三' in student_list判断元素是否在列表中。in后面只要是可遍历的序列(字符串、列表等)即可。for x in 序列:结合in就是遍历:依次取出序列中每个元素处理。
hex() 与字符串处理(约 1:08:00–1:12:00)¶
hex(整数)转成以0x为前缀的小写十六进制**字符串**,如hex(255)→'0xff'。演示查文档的标准流程:Zeal 或 python.org 搜内置函数。- 去掉
0x前缀用切片:hex_string[2:](从下标 2 开始到结尾)。 - 字符串拼接用
+,message += xxx等价于message = message + xxx,在末尾追加内容。
单元测试概念(约 1:12:00)¶
- 把大程序拆解成小单元(函数),每写完一个单元就测试它能否正常工作——软件工程中叫**单元测试(unit test)**。写完每一步都要运行验证。
VS Code 使用技巧(约 43:30–44:40,1:13:00)¶
- 快捷键
Ctrl + `(Esc 下面那个键)呼出/收起内置终端;内置终端与独立 CMD 窗口本质相同。 - 以"打开文件夹"方式使用 VS Code 时,新开终端会自动 cd 到该文件夹,省去手动切目录。
VS Code 报波浪线但命令行能跑的原因(约 1:49:00–1:54:00)¶
- VS Code 的 Lint 工具(Pylance)检查
import的包时,去的是**左侧选择的解释器环境**的Lib/site-packages里找;终端里运行则永远用**环境变量**里配置的那个环境。两者不一致时会出现"编辑器画波浪线说没有 requests,命令行却能正常跑"。 - 此问题可推广到任何语言:Java 的 package、C 的
#include <stdio.h>能找到头文件也是靠环境变量/查找路径(Visual Studio 安装时自动配好了大量路径;VS Code 轻量,需要自己配)。编辑器报错不代表代码错,可能只是环境没配对。 - 再次强调:用箭头/F5 运行"你糊涂我也糊涂",命令行里
python -V一下就知道用的是哪个解释器,绝不会搞错。
程序设计方法:流程图与任务拆解(约 1:15:00–1:23:40)¶
- 用面向过程思路拆解"两层加密"任务,现场画流程图:输入字符串 → ROT13 加密(只处理 52 个英文字母,空格标点保留)→ ASCII 转十六进制编码 → 输出;解密反之。
- 流程图三种基本形状:斜四边形(平行四边形)表示数据/输入输出,矩形表示处理流程,菱形表示判断分支(有 True/False 两个走向),用箭头连接。
- 由流程图得出需要三个工具函数:
rot13、ascii_encode、ascii_decode,再整合成encode和decode两个函数,最后用if __name__ == "__main__":写测试代码。 - ROT13 的特性:加密两次即还原(26 个字母,加 13 再加 13 回到原位),所以只需写一个函数,不分 encode/decode。
ROT13 算法实现思路(约 1:27:00–1:47:30)¶
- ROT13 = Rotate by 13 places,凯撒式轮转加密:A→N、B→O……超过 Z 绕回 A。强度极弱,常出现在 CTF 比赛签到题中。
- 实现方式一(不动脑子版,课上演示):定义两个对照串
before = "ABC...Z"、after = "NOP...M";遍历输入字符,if char in before:则index = before.find(char),取after[index]追加到结果;else原样保留(非字母不处理)。before/after定义在rot13函数内部而非全局(别处用不到)。 - 可改写:
find找不到时返回 -1,可直接用index != -1判断,省去in的判断(不算真正的优化,"回字的 N 种写法")。 - 实现方式二(动脑子版,留给大家):用
ord转数字加 13 再chr转回,注意处理超过 90(Z)时绕回 65 的截断逻辑。 - 扩展:
find(sub[, start[, end]])的可选参数——文档中**方括号表示可选参数**;指定 start/end 可限定查找区间。
示例与演示¶
第一次作业:直男表白编码升级版(ROT13 + ASCII 十六进制)(约 54:00–1:02:00,1:23:40–1:27:00,1:54:40–1:56:00)¶
- 梗:网上猜谜小游戏,发一串看不懂的代码默认翻译为"我爱你"。去年视频的简化版是把 "I love" 逐字符查 ASCII 表转成 494c4f56 这样的十六进制串;本次升级为先做 ROT13 再转 ASCII 十六进制(两层)。
- 作业仓库(Gitee 企业版,fork 后提交)里给了两样东西:
example.py:只写了 ASCII 转十六进制编码部分的最朴素示例(无函数,逐行执行)。- 框架代码:函数骨架已搭好(首次作业福利),类似"完形填空",把
pass删掉补上实现即可。 example.py逐行讲解:confession = "I love Python."→ 空字符串存结果 →for char in confession:遍历 →ord转数字 →hex转十六进制 →[2:]去0x→+=拼接 →print。- 代码风格提醒:字符串引号应统一(不要一会单引号一会双引号);缩进默认四个空格。
- 课上现场把 example 的逻辑改写进框架的
encode函数(注意变量名与参数名撞车要改名,如result),并演示了def rot13的完整实现与测试(b = rot13(rot13(a))验证两次加密还原)。 - 作业要求:完成框架里的空白(
rot13、ascii_decode、decode等);不要求写 README/截图/执行报告;老师会直接运行测试,代码跑不起来扣分较多。decode完全不提示,自己想:把十六进制串两个两个字符取出 → 转成十进制数(int(x, 16))→chr转回字符 → 拼接 → 再做一次 ROT13。 - 测试预期:
"I love Python."编码后再解码应原样还原(包括句号)。
重点与难点¶
- 对象方法调用形式(
字符串.find(...)、列表.append(...))与 C 语言习惯差异大,是 Python 最普遍的写法,必须适应。 int(x, base)的base指字符串本身的进制,常被误解为"转成 base 进制"。- 列表推导式的等价变形:循环 + 空列表 +
append与[表达式 for i in range(n)]的一一对应关系。 ''.join(list)的写法初学者不适应(用"分隔符字符串"去调 join)。- 查文档是核心能力:官方文档、Zeal/Dash、方括号=可选参数等阅读文档的基本功。
- 编辑器 Lint 报错 ≠ 代码错误,要理解解释器环境与环境变量的关系。
- 养成"先画流程图拆解任务 → 搭框架(pass 占位)→ 逐个实现 → 单元测试"的开发习惯,而不只是学语法。
关联内容¶
- 紧接回放-01:解决其遗留的 dlib/CMake 安装问题;复习其讲过的命令行执行、环境变量、克隆仓库等操作。
- 面向对象概念将在"11.1 函数进阶与类"一章正式展开,本课只是引入。
- ASCII 码、进制转换承接 C 语言前置知识;
if __name__ == "__main__"的原理仍在"模块与包"章节讲解。 - 本课作业是后续第二次作业(base64,见回放-03)的铺垫:同样围绕"编码/解码 + ASCII/进制转换"展开,难度递增。
- 爬虫章节将正式讲 requests/BeautifulSoup 与知乎分析(本课仅提语言绑定时涉及 jieba 等库)。