当前位置:首页 > Python 工业工具 > 正文内容

面向对象编程:把代码拆成"小方块"

面向对象编程:把代码拆成"小方块"

一、问题背景:2000行代码在一个文件里,改都不敢改

去年接手了一个数据分析工具。2000行代码,全在一个文件里,没有类、没有模块。

想改一个函数?不敢——因为全局变量被七八个函数共享,不知道改了取值会不会影响到其他地方。

想加一个功能?发现要在三个函数里分别加判断,缺一个就出Bug。

新同事来了,看了两天说:"这些数据怎么串来串去的?"

痛在哪里:数据和操作数据的函数是分开的。就像把扳手、螺丝、图纸全堆在一个大箱子里,找个东西要把所有东西都倒出来。

后来我用"类"重构了——把相关的数据和函数打包在一起,拆成几个小文件。每个文件300行,改起来心里有底了。

学完这一篇,你能做到:

1. 理解什么是"类"(把数据和函数打包)

2. 写一个简单的类,把数据分析和存储放在一起

3. 知道什么时候该用类、什么时候不用

---

二、技术原理:类就是"打包"

2.1 不用类的问题是代码散落

```python

不用类:数据和函数是散的

数据在这里

lot_1_id = "FAB-001"

lot_1_thickness = [1250.5, 1248.3, 1251.2]

lot_1_status = "pending"

lot_2_id = "FAB-002"

lot_2_thickness = [1247.5, 1250.8, 1249.1]

lot_2_status = "pending"

函数在那里

def analyze_lot(lot_id, data):

avg = sum(data) / len(data)

return {"id": lot_id, "avg": avg}

def mark_lot_done(lot_id):

# 怎么找到对应的变量?

pass # 不知道

```

随着Lot增多,代码越来越乱。

2.2 用类打包

```python

class LotData:

"""Lot数据类——把数据和操作打包在一起"""

def __init__(self, lot_id, thickness_data):

self.lot_id = lot_id

self.thickness = thickness_data

self.status = "pending" # pending/done/error

def analyze(self):

"""分析这批数据"""

avg = sum(self.thickness) / len(self.thickness)

std = (sum((x - avg)**2 for x in self.thickness) /

(len(self.thickness) - 1)) ** 0.5

return {"lot_id": self.lot_id, "avg": round(avg, 2), "std": round(std, 2)}

def mark_done(self):

"""标记完成"""

self.status = "done"

def summary(self):

"""打印摘要"""

print(f"[{self.lot_id}] 厚度数={len(self.thickness)}, 状态={self.status}")

```

2.3 使用这个类

```python

创建两个Lot

lot_a = LotData("FAB-001", [1250.5, 1248.3, 1251.2])

lot_b = LotData("FAB-002", [1247.5, 1250.8, 1249.1])

分析

result_a = lot_a.analyze() # 自己的数据自己分析

result_b = lot_b.analyze()

print(f"{lot_a.lot_id}: 平均={result_a['avg']}")

print(f"{lot_b.lot_id}: 平均={result_b['avg']}")

标记完成

lot_a.mark_done()

lot_a.summary() # [FAB-001] 厚度数=3, 状态=done

```

类和之前学的函数有什么区别? 函数是把"操作"打包,类是把"数据+操作"一起打包。`analyze` 函数需要你传数据进来,`LotData.analyze()` 方法直接用自己内部的数据——就像你给你的猫取个名字,猫就知道自己叫什么,不用每次都问。

---

三、实战案例:做一个设备监控类

```python

import time

import random

class Equipment:

"""FAB设备监控类"""

def __init__(self, equip_id, equip_type):

self.id = equip_id

self.type = equip_type

self.status = "IDLE"

self.temp = 25.0

self.pressure = 1.0

self.process_count = 0

def start_process(self, recipe="default"):

"""开始加工"""

if self.status == "RUNNING":

print(f"⚠ {self.id} 正在运行中")

return False

self.status = "RUNNING"

self.recipe = recipe

self.temp = 85.0 # 升温

self.pressure = 1.5

self.process_count += 1

print(f"✅ {self.id} 开始 [{recipe}] (已加工{self.process_count}次)")

return True

def stop(self):

"""停止"""

self.status = "IDLE"

self.temp = 25.0

self.pressure = 1.0

print(f"⏹ {self.id} 停止, 温度降至{self.temp}°C")

def check_temp(self):

"""检查温度是否异常"""

if self.temp > 100:

print(f"⚠ {self.id} 温度过高: {self.temp}°C!")

return False

return True

def report(self):

"""打印状态报告"""

print(f"=== {self.id} ({self.type}) ===")

print(f" 状态: {self.status}")

print(f" 温度: {self.temp}°C")

print(f" 压力: {self.pressure} torr")

print(f" 加工次数: {self.process_count}")

使用

etch = Equipment("ETCH-01", "刻蚀机")

cvd = Equipment("CVD-02", "沉积设备")

etch.report()

etch.start_process("OXIDE_ETCH") # 开始加工

etch.check_temp() # 检查温度

etch.stop() # 停止

cvd.start_process("SIN_DEP")

cvd.report()

```

为什么用类管理设备比用字典好? 如果用字典,你要写 `device['status'] = 'RUNNING'`,然后在另一个函数里 `if device['status'] == 'RUNNING'`——状态分散在代码各处,改了设备结构的某个字段名,所有用到的地方都要改。用类之后,状态和操作都在类内部,外面只调用 `etch.start_process()`,底层怎么实现你改里面就行,外面不用动。这就是"封装"的好处。

---

四、效果对比

| 维度 | 不用类(散装) | 用类打包 |

|------|--------------|---------|

| 数据位置 | 分散在各种变量里 | 在类内部统一管理 |

| 新增函数 | 加一个新函数要小心别影响了其他 | 加在类内部,自己管自己 |

| 阅读理解 | 看完整篇才知道数据怎么流动的 | 看一个类就知道 |

| 多人协作 | 容易互相覆盖变量 | 各自用各自的类 |

---

五、自己动手

```python

练习:做一个 LotTracker 类

功能:记录和分析一批Lot数据

class LotTracker:

def __init__(self, line="ETCH"):

self.line = line

self.lots = [] # 存放Lot数据

def add_lot(self, lot_id, thickness_avg):

"""添加一批Lot"""

self.lots.append({"id": lot_id, "avg": thickness_avg})

def total_count(self):

"""返回Lot总数"""

pass # ✏️ 你的代码

def avg_yield(self):

"""返回所有Lot的平均厚度"""

pass # ✏️ 你的代码

def summary(self):

"""打印统计报告"""

pass # ✏️ 你的代码

尝试使用

tracker = LotTracker("ETCH")

tracker.add_lot("A001", 1250.5)

tracker.add_lot("A002", 1248.3)

tracker.summary()

```

思考题

1. 类和字典有什么区别?什么时候用类,什么时候用字典就够了?

2. `__init__` 为什么叫"初始化"?不写 `__init__` 行不行?

3. 类里可以有另一个类吗?(提示:嵌套类)

---

六、常见误区

| 问题 | 表现 | 正确做法 |

|------|------|---------|

| 啥都写成类 | 类套类,复杂死了 | 简单的逻辑用函数就够了 |

| 类太大了 | 一个类500行 | 拆成多个小类 |

| 属性在外面直接改 | `lot.status = 'xxx'` 全是硬编码 | 用方法 `lot.mark_done()` 来改 |

| 学了面向对象不会用 | 不知道什么场合用 | 发现数据散落各处的时候就用类 |

---

关于"面向对象"我多说几句

很多人学Python时被"面向对象"劝退了——太难了。

我的建议是:菜鸟阶段不用硬学。你写100行的脚本,用函数完全够了。当你发现:

  • 一个功能改了、其他地方全崩了
  • 代码超过500行,找变量定义要找半天
  • 改了A功能、影响B功能

这个时候再回来学面向对象,一学就会——因为你有"需求"了。

---

> 💬 你用类写过什么项目?觉得类真的有用还是觉得花架子?

> 📚 收藏+点赞,下一篇开始做项目 👆

相关文章

FAB工程师学Python的正确路径(附学习地图)

FAB工程师学Python的正确路径(附学习地图)

FAB工程师学Python的正确路径(附学习地图) 我带过一个实习生,非科班出身,学了3个月Python,第一个月工资就涨了2000。 也有干了5年的工艺工程师,手动导数据画图画了5年,月薪还是那点钱...

Python+半导体数据工具完整自学路线(零基础→项目实战)

Python+半导体数据工具完整自学路线(零基础→项目实战)

Python+半导体数据工具完整自学路线(零基础→项目实战) 经常有人问我:我想学Python做FAB数据分析,从哪里开始? 今天我把完整路线画出来,从零基础到能独立做项目,按这个走,90天能出师。...

SPC/MES/FDC工具全家桶:工程师必备Python脚本合集

SPC/MES/FDC工具全家桶:工程师必备Python脚本合集

SPC/MES/FDC工具全家桶:工程师必备Python脚本合集 我在FAB干了15年,最值钱的东西不是经验,是一个攒了多年的Python工具箱。 今天把这个工具箱的核心部分分享出来,从数据采集到SP...

Python日报自动化:MES数据一键生成Excel报告(附完整源码)

Python日报自动化:MES数据一键生成Excel报告(附完整源码)

Python日报自动化:MES数据一键生成Excel报告(附完整源码) 1. 我的血泪史:每天2小时的日报工作 2018年,我在FAB做整合工程师的时候,每天早上第一件事不是分析数据,而是做日报。从M...

Python设备故障预测:XGBoost让FAB的设备维护从被动到主动

Python设备故障预测:XGBoost让FAB的设备维护从被动到主动

Python设备故障预测:XGBoost让FAB的设备维护从被动到主动 1. 问题背景:被动维修的代价 FAB里最贵的不是设备,是设备宕机造成的产能损失。一台光刻机价值$100M+,停机1小时损失约$...

Python晶圆良率分析实战:从数据清洗到可视化(附完整代码)

Python晶圆良率分析实战:从数据清洗到可视化(附完整代码)

Python晶圆良率分析实战:从数据清洗到可视化(附完整代码) 1. 问题背景:我的第一次良率分析 2016年,我在FAB做工艺工程师的时候,第一次被要求分析一批良率异常。工程师把数据发给我——一个E...