Python面向对象编程——让代码和现实世界对齐
一、OOP 解决了什么问题编程本质上是把现实问题翻译成计算机能执行的逻辑。那现实世界长什么样——它不是一堆零散的变量和顺序执行的过程而是由一个个独立的个体组成的你用计算器不是拿一堆电路元件拼凑运算逻辑而是直接按按钮。你存钱不是手动改 Excel而是让账户对象帮你处理。面向过程写计算器长这样——数据和操作数据的过程是分离的# 面向过程数据是数据流程是流程n1int(input(第一个运算数))n2int(input(第二个运算数))opinput(请输入运算符)ifop:print(f{n1}{n2}{n1n2})elifop-:print(f{n1}-{n2}{n1-n2})面向对象则把数据和行为打包进一个整体# 面向对象先有计算器这个东西再操作它calcCalculator()calc.input()calc.result()面向对象代码量不一定会少但三个优势是面向过程给不了的面向过程面向对象复用每次用都得复制粘贴流程创建新对象就能反复调方法模块化代码是紧耦合的整体类可拆分到独立文件各管各的分工边界不清一改动牵全身一拨人写类一拨人用类一句话面向过程围绕流程组织代码面向对象围绕对象组织代码。你的大脑本来就用对象来理解世界让代码结构跟你大脑对齐写起来才不拧巴。二、类和对象图纸和实物类对某一类事物的抽象描述定义了这类事物有什么和能干什么。对象符合类描述的一个具体个体是类这张图纸生产出来的实物。如果Person是类那刘备就是一个对象。类描述事物分两方面静态特征 → 属性变量姓名、年龄动态特征 → 方法函数说话、走路classPerson:一个简单的人类模型name无名age18defintroduce(self):print(f我叫{self.name}今年{self.age}岁)# 创建对象并赋值lbPerson()lb.name刘备lb.age61lb.introduce()# 输出我叫刘备今年61岁从内存角度看类本质就是自定义的数据类型——int是个类10是其对象是其方法。Python 里一切皆对象这句话落到内存里就是连int、str的变量也遵循类→对象这套逻辑。三、类的内部结构拆解3.1 类变量 vs 实例变量定义位置归属修改影响类变量class块内、方法外类本身所有对象共享一处改处处变实例变量方法内通过self.xxx定义单个对象独有互不影响classRobot:population0# 类变量统计机器人数def__init__(self,name):self.namename# 实例变量每个机器人名字不同Robot.population1# 引用类变量Robot.xxx 或 self.__class__.xxxdefdestroy(self):Robot.population-1print(f{self.name}已销毁剩余{Robot.population}台)classmethoddefreport(cls):# cls 是类本身的引用print(f当前{cls.population}台机器人在线)踩坑提醒类变量和实例变量同名时self.xxx优先访问实例变量。如果你不小心用self.population 100会悄悄创建一个实例变量类变量纹丝不动——这种 bug 很难排查。3.2 三种方法对象方法、类方法、静态方法classDemo:defmethod(self):# 对象方法self 接收当前对象passclassmethoddefclass_method(cls):# 类方法cls 接收类本身passstaticmethoddefstatic_method():# 静态方法不自动传任何参数就是个普通函数pass调用方式差异obj.method()→ Python 自动填self等价于Demo.method(obj)Demo.class_method()→ Python 自动填cls不依赖具体对象Demo.static_method()→ 直接调跟类外函数没区别什么时候用哪个如果你需要访问实例数据self.xxx→ 对象方法如果需要访问类变量cls.xxx→ 类方法如果纯属工具函数跟类和实例都无关 → 静态方法。别三种混着用逻辑会很乱。3.3 构造方法__init__对象创建时自动调用用于初始化。几乎所有类都有它classStudent:def__init__(self,name,score):self.namename self.scorescore注意点__init__不是真正的构造函数——先由__new__创建对象再用__init__初始化。日常你只需要关心__init__。3.4 Python 式私有成员Python没有真正的 private 关键字靠两套约定_name单下划线纯约定“我是内部成员别碰”Python 不会拦你。__name双下划线触发名称改写name mangling变成_ClassName__name外部直接访问会AttributeError。classBankAccount:def__init__(self,owner,balance):self.ownerowner# 公有self.__balancebalance# 私有外部碰不到defdeposit(self,amount):ifamount0:self.__balanceamountdefget_balance(self):returnself.__balance需要保护的数据用双下划线需要暴露的用公有方法。这就是封装的落地——数据藏在对象里面外面只能通过你允许的方法操作。3.5 文档字符串类、方法的第一行字符串就是文档靠__doc__读取classStudent:学生模型存储学号和成绩defexam(self,subject):参加考试 Args: subject: 考试科目 passprint(Student.__doc__)# 学生模型存储学号和成绩print(Student.exam.__doc__)# 参加考试...好的文档字符串 给别人用的说明书。尤其你写类给别人调的时候__doc__是救命稻草。四、继承复用与扩展class子类(父类):def__init__(self,...):父类.__init__(self,...)# 必须显式调用三条铁律子类__init__必须显式调父类的__init__否则父类的初始化逻辑不会执行——静默 bug很难排查。如果子类没定义__init__Python 会自动沿继承链往上找找到就用。Python 支持多继承class C(A, B)但层次一深就是灾难能用单继承就别碰多继承。classMember:def__init__(self,name):self.namenamedefshow(self):print(fMember:{self.name})classTeacher(Member):def__init__(self,name,subject):Member.__init__(self,name)# 必须显式调用self.subjectsubjectdefshow(self):# 重写父类方法Member.show(self)# 想保留父类逻辑显式调print(f科目:{self.subject})五、多态同一个接口不同的行为多态的本质方法查找沿着「对象 → 类 → 父类」链条往上走找到就停。所以不同子类重写同名方法后调用同样的obj.show()会产生不同效果。classAnimal:defspeak(self):return...classDog(Animal):defspeak(self):return汪汪classCat(Animal):defspeak(self):return喵喵# 同一接口不同行为forpetin[Dog(),Cat()]:print(pet.speak())# 汪汪 / 喵喵多态的价值不在于省代码而在于写通用逻辑。你能写一个feed(animal)函数传入任何动物的子类都正常工作——不用判断是狗还是猫。这是 OOP 最强力的抽象能力。六、特殊方法让你的类像内置类型一样工作Python 把__xxx__这种双下划线方法叫 special method魔法方法。它不是语法糖是 Python 的语言协议。你实现这些方法你的类就能被print、被len、被、被[]索引特殊方法触发场景你的类能干嘛__str__print(obj),str(obj)友好的字符串表示__len__len(obj)获取长度__getitem__obj[i]索引访问__lt__obj1 obj2比较大小__add__obj1 obj2对象拼接一个完整的栈类一次性演示全部classStack:def__init__(self,*items):self._itemslist(items)defpush(self,item):self._items.append(item)defpop(self):returnself._items.pop()ifself._itemselseNonedef__str__(self):returnstr(self._items)def__len__(self):returnlen(self._items)def__getitem__(self,i):returnself._items[i]if0ilen(self)elseNonedef__add__(self,other):拼接两个栈returnStack(*(self._itemsother._items))有了这些你写的栈用起来就跟list一样自然sStack(A,B,C)print(s)# [A, B, C] ← __str__print(len(s))# 3 ← __len__print(s[1])# B ← __getitem__s2sStack(D,E)# ← __add__特殊方法的本质实现协议融入生态。定义了__len__你的类就能塞进任何接受len()的通用函数里。这就是 Python「一切皆对象」的真正威力。七、异常处理优雅地应对意外异常 ≠ 错误。它是程序运行中的意外情况你得提前写好预案。7.1 基础结构try / except / else / finallytry:numint(input(输入数字))result100/numexceptValueError:print(不是数字)exceptZeroDivisionError:print(不能除以 0)else:print(f结果{result})# 没异常才执行finally:print(不管有没有异常我都会执行)except指定异常类型 → 精确捕获不指定 → 捕获所有危险别这么干。else没异常才走这里跟try里的代码分开逻辑更清晰。finally无论如何都执行用来释放资源关闭文件、断开连接。7.2 自定义异常继承Exception用raise抛出用as接收classInsufficientBalanceError(Exception):余额不足异常def__init__(self,balance,required):self.balancebalance self.requiredrequireddefwithdraw(balance,amount):ifamountbalance:raiseInsufficientBalanceError(balance,amount)returnbalance-amounttry:withdraw(100,500)exceptInsufficientBalanceErrorase:print(f余额{e.balance}需要{e.required}还差{e.required-e.balance})什么时候自定义异常当你需要区分这是业务逻辑的意外和这是程序的 bug时。ValueError太泛了BalanceNotEnoughError一看就懂。八、正则表达式文本处理的瑞士军刀正则表达式跟 OOP 看似两个话题但实际项目中它们经常结伴出现——你写一个用户注册类构造方法里拿正则验证邮箱、手机号、密码强度不合法就抛异常。它就是文本验证和提取的标准工具。8.1 什么时候用正则验证邮箱格式对不对、手机号是不是 11 位数字提取从日志里抠出 IP 地址、从 HTML 里抓内容替换把一串文本中的所有电话号码打码分割按多种分隔符拆分字符串8.2 re 模块核心方法importre text价格¥99.9库存20 件re.search(r\d\.?\d*,text)# 找第一个匹配99.9re.match(r价格,text)# 从开头匹配必须从头匹配re.findall(r\d,text)# 找所有匹配[99, 9, 20]re.sub(r\d,XX,text)# 替换所有数字价格¥XX.XX库存XX 件re.split(r[,],text)# 按中文逗号或英文逗号分割searchvsmatchmatch要求从字符串开头匹配search在整个字符串中搜索。日常验证用match提取用search或findall。8.3 常用元字符速查符号含义示例.任意字符除换行a.b→aab,acb*前一个字符 0 次或多次ab*→a,ab,abb前一个字符 1 次或多次ab→ab,abb不匹配a?前一个字符 0 次或 1 次ab?→a,ab{n}恰好 n 次\d{11}→ 11 位数字{n,m}n 到 m 次\d{6,18}→ 6-18 位^字符串开头^1→ 必须以 1 开头$字符串结尾\.com$→ 以 .com 结尾[]字符类[a-z]→ 任意小写字母()分组捕获(\d{3})-(\d{4})→ 捕获两段数字\d数字 [0-9]\d→ 一串数字\w字母数字下划线 [a-zA-Z0-9_]\w→ 单词\s空白字符\s→ 连续空白8.4 贪婪 vs 非贪婪默认贪婪匹配——尽可能多吃字符。加?变非贪婪——尽量少吃textdiv内容1/divdiv内容2/divre.findall(rdiv.*/div,text)# 贪婪[div内容1/divdiv内容2/div] 吞掉了全部re.findall(rdiv.*?/div,text)# 非贪婪[div内容1/div, div内容2/div]这是正则最容易踩的坑之一。提取 HTML 内容时记住加?。8.5 预编译优化多次使用同一个正则用re.compile提前编译性能更好、代码更清晰# 不好每次调用都重新编译正则defvalidate_phone(phone):returnbool(re.match(r^1[3-9]\d{9}$,phone))# 好编译一次复用PHONE_PATTERNre.compile(r^1[3-9]\d{9}$)defvalidate_phone(phone):returnbool(PHONE_PATTERN.match(phone))8.6 三个实战常用正则# 邮箱EMAILre.compile(r^[\w.-][\w-]\.[a-zA-Z]{2,}$)# 手机号中国大陆PHONEre.compile(r^1[3-9]\d{9}$)# 提取日期 YYYY-MM-DDDATE_EXTRACTORre.compile(r\d{4}-\d{2}-\d{2})8.7 用类封装验证器——正则 × OOP把正则封装进类配合异常处理是实际项目中最常见的组合importreclassValidationError(Exception):输入验证失败passclassInputValidator:输入验证器——OOP 正则 异常的实战组合EMAIL_REre.compile(r^[\w.-][\w-]\.[a-zA-Z]{2,}$)PHONE_REre.compile(r^1[3-9]\d{9}$)classmethoddefemail(cls,value):ifnotcls.EMAIL_RE.match(value):raiseValidationError(f邮箱格式无效:{value})classmethoddefphone(cls,value):ifnotcls.PHONE_RE.match(value):raiseValidationError(f手机号格式无效:{value})# 使用try:InputValidator.email(userexample.com)# OKInputValidator.phone(13812345678)# OKInputValidator.email(not-an-email)# 抛异常exceptValidationErrorase:print(e)这个例子把前面学的类、类方法、正则表达式、自定义异常全用上了。以后你在 FastAPI 里写 Pydantic validator 或者写数据校验中间件套路跟这一模一样。总结这篇覆盖了 Python OOP 的核心知识 正则表达式。用一张表收尾概念一句话类一类事物的抽象描述图纸对象类的具体实例实物封装数据 方法打包进对象用私有成员控制访问继承子类复用父类代码显式调父类.__init__多态同名方法沿继承链查找不同子类不同行为特殊方法实现__str__/__len__等协议让自定义类融入 Python 生态异常try/except/else/finally 自定义异常优雅应对意外正则文本验证和提取的标准工具搭配re.compile预编译这些是后续学 FastAPI、Pydantic 模型、AI Agent 框架的绝对基础——框架源码里全是类和继承业务逻辑里全是正则和异常。地基打牢了上层才不会晃。

相关新闻

谁懂啊,最近发现一个适合日常薅小优惠的小渠道,就在千间

谁懂啊,最近发现一个适合日常薅小优惠的小渠道,就在千间

给大家整理好简单操作流程,亲测顺利领到:1.先下载 千间2.输入口令: 千问新人福利 yPBm3m3.直接领取 8 元通用券4.后续下单就能抵扣平时下班点奶茶、点外卖、出门打车都能用。 最近天气闷热,经常想点冰饮,刚好能用上…

2026/10/5 23:40:50 阅读更多 →
基于8051单片机的HRTOS双任务LED应用实例

基于8051单片机的HRTOS双任务LED应用实例

1. 前言传统8051裸机开发中,当程序功能逐渐增加时,通常需要在主循环中不断判断各种状态。例如:while(1) {if(flag1)task1();if(flag2)task2(); }当任务数量增加后,代码维护难度逐渐提升。RTOS通过任务调度机制,可以将不…

2026/10/12 18:59:15 阅读更多 →
ABB工业机器人RAPID编程实战:从架构设计到焊接应用

ABB工业机器人RAPID编程实战:从架构设计到焊接应用

1. 项目概述:从“会动”到“会干活”的工业机器人 提到工业机器人,很多人脑海里浮现的是汽车生产线上那些挥舞着机械臂、精准焊接或搬运的“钢铁侠”。但要让这些价值不菲的设备真正“会干活”,核心就在于程序。ABB作为全球工业机器人领域的巨…

2026/10/5 14:29:35 阅读更多 →

最新新闻

json.lib完整工程集成指南:从下载到验证的避坑全攻略

json.lib完整工程集成指南:从下载到验证的避坑全攻略

简介:面向需要在C项目中处理JSON数据的开发者,这份资源提供了可直接使用的JsonCpp库文件和修改后的完整工程。JsonCpp是一套跨平台的JSON解析与生成库,支持在Windows、Linux、macOS等多种系统使用。这一版本以JsonCpp 0.5.0源码为基础&#x…

2026/10/13 14:27:32 阅读更多 →
scikit-learn 复合估计器完全指南:Pipeline、FeatureUnion 与 ColumnTransformer 的合并与构造

scikit-learn 复合估计器完全指南:Pipeline、FeatureUnion 与 ColumnTransformer 的合并与构造

文档机器学习教程 【免费下载链接】sklearn-doc-zh :book: [译] scikit-learn(sklearn) 中文文档 项目地址: https://gitcode.com/gh_mirrors/sk/sklearn-doc-zh 点击查看 免费下载 复合估计器(composite estimators)…

2026/10/13 14:27:32 阅读更多 →
Agent技能系统设计实战:从工具定义到稳定调用的完整方案

Agent技能系统设计实战:从工具定义到稳定调用的完整方案

Agent 项目总在"就差最后一步"时崩掉?如果你带过稍微复杂一点的 Agent 项目,大概率见过这样的现场:模型已经正确理解用户意图,也知道该调用哪个工具,结果因为工具描述写得含糊、参数传错、超时没人管&#x…

2026/10/13 14:27:32 阅读更多 →
缠论K线包含处理插件源码:合并逻辑、方向判断与通达信实现

缠论K线包含处理插件源码:合并逻辑、方向判断与通达信实现

简介:这份通达信缠论K线包含处理插件源码,面向熟悉通达信平台且希望深入学习缠论量化分析的开发者。它提供了一套基于VC的DLL插件实现,核心代码集中在ChanLunTdx.cpp与util.cpp中,围绕K线包含判断、合并以及笔、线段、中枢的构建逻…

2026/10/13 14:27:32 阅读更多 →
AI痕迹太重?八款降AI率工具实测对比与选型指南

AI痕迹太重?八款降AI率工具实测对比与选型指南

年初那段时间,我帮几个做自媒体和内容代运营的朋友审核稿件,几乎每隔一两天就会收到“这篇AI痕迹太重了,客户那边查出来AI率80%多,退回来重写”的反馈。起初我还以为是检测工具误伤,后来自己拿了同一篇文章分别丢进几个…

2026/10/13 14:27:32 阅读更多 →
MATLAB 安装 MinGW-w64 支持包:MEX 编译配置与避坑指南

MATLAB 安装 MinGW-w64 支持包:MEX 编译配置与避坑指南

简介:这份支持包面向希望利用编译型语言提升MATLAB计算性能的科研与工程人员,适用于MATLAB 2023B/2024A环境。它集成了MinGW-w64编译器,可调用GCC工具链在Windows平台编译C、C和Fortran代码,并通过MEX接口将原生程序嵌入MATLAB&am…

2026/10/13 14:26:30 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →