跳转至

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...Z 26 个字母"过于朴实",程序员追求自动生成。
  • 背景知识 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 等库)。