⌨️ 第三章 数值和数据的处理方法
📄 一句话概括

现实世界的数据很少是单个数字——一个学生有姓名、年龄、成绩三种信息。结构体把【不同类型的几样】捆成一包当一张记录卡,枚举把【只有几种可能的取值】逐个命名——自定义类型的两块基石。

📝 本节和前面几节的关系

3-4~3-8 处理的都是【一种类型】的数据,这一篇开始【造自己的类型】。回收 C++ 课第八章(结构体与共用体)与第十章(类——结构体加方法的后继),数据库课 5-6 的【实体与属性】是同一个思想在数据设计层的投影。

一、结构体:不同类型捆成一包

描述一个学生:姓名是字符串、年龄是整数、平均分是浮点——三种类型,各有用途,拆着传(传三个变量)又散又容易漏。结构体的思路:打包成一个整体:

struct Student {          // C 语言的写法
    char name[20];        // 字符串(C 的字符数组,见 3-9 的 \0)
    int  age;
    float score;
};

打包之后,一个变量就是【一张完整记录卡】:

# Python 里用 dataclass(现代等价物)
from dataclasses import dataclass

@dataclass
class Student:
    name: str
    age: int
    score: float

stu = Student(name="王明", age=16, score=92.5)
print(stu.name, stu.score)   # 王明 92.5 —— 按字段名取

价值:字段有名(不怕传错位)、可以整体传递/存入列表、加字段只改一处。面向对象里的【类】就是结构体的进化——多了方法(行为)。

二、枚举类型:有限取值逐个命名

有些量天生只有几种可能:星期一到日、季节四季、订单状态【待付款/已付款/已发货】。用裸数字记(0=周一、1=周二)就是 3-6 批判过的魔法数字——枚举把它们命名:

from enum import Enum

class Weekday(Enum):
    MON = 1
    TUE = 2
    SUN = 7

today = Weekday.MON
print(today)                # Weekday.MON
print(today == Weekday.MON) # True

三重好处:可读(Weekday.MON 比 1 明白)、防错(写成 Weekday.WED 拼错当场报错,写 3 谁也不知道对不对)、取值封闭(只有这几个成员)。

三、两者配合:记录卡+下拉菜单

实际项目里常组合:学生结构体里的【性别】【年级】字段,用枚举当类型——结构体管【有哪几项】,枚举管【某项只能填哪几个】。数据库课 5-19 设计书评网站表时的【确定属性取值】是同一件事的设计期版本。

四、动手 Demo:记录卡装进列表

from dataclasses import dataclass
from enum import Enum

class Level(Enum):
    A = "优秀"
    B = "良好"

@dataclass
class Student:
    name: str
    age: int
    level: Level

roster = [Student("王明", 16, Level.A), Student("李华", 17, Level.B)]
for stu in roster:
    print(stu.name, stu.level.value)

看到什么算成功:

王明 优秀
李华 良好

读结果:结构体当元素装进列表(3-8 的走廊里住起了【记录卡】),枚举用 .value 取出人类可读的字面值——两个自定义类型合体,数据立刻有模有样。

五、30 秒实验

跑 Student("王明", 16, 99)——dataclass 不拦类型不匹配(99 不是 Level),但打印 stu.level 会露馅。换成 C 的 enum 或 Java 的 enum 编译器就会拦。枚举的防错力取决于语言的检查强度——30 秒看清这一点。

六、常见误区

  1. 【结构体和类是两种完全不同的东西】——错。C++ 里 struct 和 class 只差默认访问权限;结构体是【只有数据的类】,类是【加了行为的结构体】。
  2. 【枚举就是给数字起别名,用常量代替也行】——不完整。枚举是封闭集合:类型系统保证取值不越界、能穷举、能配合 switch/match;散装常量没有这些保护。
  3. 【数据都该用结构体打包】——过犹不及。单个数值、简单的键值对(3-13 的字典)硬包成结构体反而啰嗦;字段的种类和关系变复杂了,才是打包的时机。
自测三问(点开对答案) 1. **结构体解决什么问题?** 答:把【不同类型的若干相关数据】捆成一个整体——字段有名、可整体传递、加字段只改定义一处。 2. **枚举比【散装常量】强在哪?** 答:封闭取值+类型检查——只可能取定义过的成员,拼错或越界当场暴露;可读性也从【数字 3】升级为【命名成员】。 3. **类和结构体的关系?** 答:类=结构体+方法(行为);C 的 struct 只有数据,C++/Java/Python 的 class 让【数据】和【操作数据的函数】住到一起。

相关笔记