第8集:抽象思维训练——程序员的基本功
学习目标
通过本集的学习,你将能够:
- 理解什么是抽象
- 掌握从具体到抽象的方法
- 识别生活中的抽象例子
- 在编程中运用抽象思维
8.1 什么是抽象?
抽象是编程中最重要的思维方式之一。
定义
抽象:忽略不重要的细节,关注本质特征。
简单说:把复杂的东西变简单,抓住核心!
生活中的例子
例子1:地图
真实的城市:
- 每一栋建筑
- 每一棵树
- 每一个垃圾桶
- 每一块地砖
抽象后的地图:
- 主要道路
- 标志性建筑
- 你要找的地方地图忽略了很多细节,但保留了最重要的信息!
例子2:公交车线路图
真实的道路:
- 弯曲的街道
- 上坡下坡
- 每个红绿灯
抽象后的线路图:
- 直线表示线路
- 圆点表示站点
- 换乘点标记虽然不真实,但更容易理解!
例子3:财务报表
真实的交易:
- 每一笔收入的时间、地点、方式
- 每一笔支出的细节
- 成千上万条记录
抽象后的报表:
- 总收入
- 总支出
- 净利润
- 关键指标一眼就能看出盈亏!
抽象的好处
- 简化复杂问题:把复杂变简单
- 抓住本质:关注真正重要的
- 便于沟通:用简单方式分享复杂想法
- 可复用:抽象的概念可以用在很多地方
8.2 从具体到抽象
让我们看看如何从具体事物中抽象出概念。
例子:从具体动物到抽象概念
具体的动物
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 金毛 │ │ 波斯猫 │ │ 金鱼 │
│ 汪汪叫 │ │ 喵喵叫 │ │ 游来游去 │
│ 摇尾巴 │ │ 舔爪子 │ │ 吐泡泡 │
└─────────┘ └─────────┘ └─────────┘第一步:找共同点
它们都有什么共同特点?
- 都是活的
- 都需要吃东西
- 都能移动
- 都有名字
第二步:抽象出"动物"概念
抽象概念:动物
特点:
- 有生命
- 需要进食
- 能活动
- 有名字第三步:进一步抽象
还能继续抽象吗?
动物 → 生物 → 物体 → ...但是!抽象不是越抽象越好!
- 太具体:太繁琐,不好用
- 太抽象:丢失太多信息,也不好用
- 恰到好处:取决于你的目的!
8.3 编程中的抽象
编程中到处都是抽象!
例子1:变量
具体:
这个盒子里现在放的是 5,
等一下可能放 10,
再等一下可能放 42...
抽象成变量:
int x;
x = 5;
x = 10;
x = 42;
抽象概念:
x 是一个"容器",可以放不同的值例子2:函数
具体操作:
把 1 和 2 加起来 → 3
把 3 和 4 加起来 → 7
把 5 和 6 加起来 → 11
抽象成函数:
def add(a, b):
return a + b
抽象概念:
add 是一个"加法机器",
给它两个数,它返回和例子3:数据结构
具体:
购物清单1:[苹果, 香蕉, 橙子]
购物清单2:[牛奶, 面包]
待办事项:[写代码, 看书, 锻炼]
抽象成列表:
list = [item1, item2, item3, ...]
抽象概念:
列表是一个"有序容器",
可以放多个东西,按顺序排列例子4:面向对象
具体:
金毛:
- 名字:大黄
- 年龄:3岁
- 动作:汪汪叫、摇尾巴
波斯猫:
- 名字:咪咪
- 年龄:2岁
- 动作:喵喵叫、舔爪子
抽象成类:
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
pass
抽象概念:
Animal 是所有动物的"模板",
定义了共同的特征和行为8.4 抽象思维训练
让我们做一些练习来训练抽象思维!
练习1:从具体事物中抽象
看看这些具体事物,你能抽象出什么概念?
具体事物:
- 苹果、香蕉、橙子、葡萄
- 轿车、卡车、公交车、自行车
- 钢笔、铅笔、圆珠笔、毛笔
- 加法、减法、乘法、除法
请思考:
每一组可以抽象成什么概念?参考答案:
- 水果
- 交通工具
- 书写工具
- 运算(或数学运算)
练习2:识别抽象层次
看看这些概念,哪些更抽象,哪些更具体?
概念:
A. 金毛
B. 狗
C. 动物
D. 生物
从具体到抽象排序:
(更具体) A → B → C → D (更抽象)练习3:在编程中运用抽象
假设你要写一个程序处理不同形状:
具体形状:
- 圆形:有半径,可以算面积
- 矩形:有长和宽,可以算面积
- 三角形:有底和高,可以算面积
如何抽象?
思路:
1. 找出共同点:都能算面积
2. 抽象出"形状"概念
3. 定义一个通用的"计算面积"接口用 Python 实现:
from abc import ABC, abstractmethod
import math
class Shape(ABC):
"""抽象的形状类"""
@abstractmethod
def area(self):
"""计算面积(抽象方法,子类必须实现)"""
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return math.pi * self.radius * self.radius
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
# 使用
shapes = [
Circle(5),
Rectangle(3, 4),
]
for shape in shapes:
print(f"面积: {shape.area()}")这就是抽象的威力!我们可以用统一的方式处理不同的形状。
8.5 抽象的层级
抽象不是非黑即白的,有不同的层级。
最具体
│
├─ 你正在看的这台 MacBook Pro
│
├─ 笔记本电脑
│
├─ 电脑
│
├─ 电子设备
│
├─ 设备
│
└─ 物体
│
最抽象选择合适的抽象层级:
- 如果你要修这台电脑 → 具体到"这台 MacBook Pro"
- 如果你要买电脑 → 抽象到"笔记本电脑"或"电脑"
- 如果你在讨论物流 → 抽象到"电子设备"或"物体"
没有最好的抽象,只有最合适的抽象!
8.6 编译原理中的抽象
编译原理中充满了抽象!
例子1:Token
源代码中的字符:
'int' 'result' '=' '1' '+' '2' ';'
抽象成 Token:
[INT, ID("result"), ASSIGN, NUMBER(1), PLUS, NUMBER(2), SEMICOLON]
抽象概念:
忽略具体的字符细节,
关注它们的"类型"和"值"例子2:抽象语法树(AST)
Token 流:
[INT, ID("result"), ASSIGN, NUMBER(1), PLUS, NUMBER(2), SEMICOLON]
抽象成 AST:
=
/ \
result +
/ \
1 2
抽象概念:
忽略具体的 Token 顺序,
关注程序的"结构"例子3:中间表示(IR)
AST:
=
/ \
result +
/ \
1 2
抽象成三地址码:
t1 = 1 + 2
result = t1
抽象概念:
忽略具体的语法树结构,
关注"操作"的序列可以看到,编译的过程就是一层一层抽象的过程!
8.7 自测一下
问题 1
什么是抽象?
A) 把简单变复杂
B) 忽略不重要的细节,关注本质特征
C) 画画
D) 忘记事情
问题 2
从"金毛、哈士奇、柯基"可以抽象出什么概念?
A) 植物
B) 狗
C) 猫
D) 汽车
问题 3
关于抽象层级,以下说法正确的是?
A) 越抽象越好
B) 越具体越好
C) 取决于使用场景,选择合适的层级
D) 抽象层级不重要
问题 4
请举一个生活中抽象的例子(开放题)
答案:
- B
- B
- C
- 参考答案:地图、公交车线路图、财务报表等(合理即可)
8.8 下集预告
下两集,我们将学习:正则表达式入门!
我们会学习:
- 为什么需要正则表达式
- 基本字符匹配
- 量词:*, +, ?, {n}
- 字符类、分组、锚点
- 实战:识别数字、标识符
准备好了吗?我们下集见!
参考资料
- 《程序员的思维修炼》
- SICP(《计算机程序的构造和解释》)
- 抽象艺术相关书籍