Python中使用封装类还是函数以及它们的区别
前言该用类还是用函数是写 Python 时绕不开的选择。一句话概括函数封装的是 行为类封装的是状态 一组操作状态的行为。如果一件事只是一次输入到 一次输出的变换函数就够了如果一件事要在多次调用之间记住某些东西、 并且有一组相关的操作要围绕这份状态展开类通常更合适。常见的误解有两个。一个是面向对象更高级所以什么都该写成类于是出现了 一堆只有一个staticmethod的类纯粹把函数包了一层。另一个是类一定比函数 重于是该维护状态的地方硬用全局变量结果到处都能改、难以测试。两种都源于 没分清要不要状态这个关键点。本文按本质区别 → 各自适用的场景 → 闭包作为轻量替代 → 数据类简化封装来讲 最后给出一个对照表。示例基于 Python 3dataclass需要 3.7 及以上。一、本质区别行为 vs 状态加行为函数接收参数、返回结果通常不保留调用之间的状态# 适用于 Python 3.8def area(width, height):return width * heightprint(area(3, 4)) # 12类则定义一个模板用它创建的实例各自带一份状态属性并拥有一组可以 操作这份状态的方法# 适用于 Python 3.8class Rectangle:def __init__(self, width, height):self.width widthself.height heightdef area(self):return self.width * self.heightr Rectangle(3, 4)print(r.area()) # 12print(r.width) # 3 状态被记住关键差别Rectangle的实例记得自己的width和height而area函数每次都要重新把两个参数传进去。二、什么时候用函数逻辑是无状态的相同输入必得相同输出。是一次输入到一次输出的变换格式化字符串、计算、解析。不需要在调用之间记住任何东西。你想让代码容易被单测纯函数最好测给输入、验输出即可。# 适用于 Python 3.8def slugify(title):把标题变成 URL 友好的短横线形式。return title.strip().lower().replace( , -)print(slugify(Hello World)) # hello-world这里没有任何需要记住的东西函数就是最自然的表达。三、什么时候用类有状态需要在多次调用之间保持连接、余额、计数器、配置。有一组相关操作围绕同一份状态存款 / 取款 / 查余额。需要多态多个类实现同一套接口运行时替换。需要身份两个实例即使数据相同也代表不同对象。# 适用于 Python 3.8class Account:def __init__(self, balance0):self.balance balancedef deposit(self, amount):self.balance amountreturn self.balancedef withdraw(self, amount):if amount self.balance:raise ValueError(余额不足)self.balance - amountreturn self.balanceacc Account(100)print(acc.deposit(50)) # 150print(acc.withdraw(30)) # 120余额这份状态被实例记住两个操作共享它——这正是类擅长的场景。四、闭包不用类也能封装状态如果只需要一份状态 一两个操作闭包closure是轻量替代不必动用 类# 适用于 Python 3.8def make_counter():count 0def step():nonlocal countcount 1return countreturn stepc make_counter()print(c(), c(), c()) # 1 2 3count被闭包关在函数里外部访问不到效果类似私有属性。什么时候用闭包、 什么时候用类经验是只有一两个操作、不需要继承、不需要多态闭包更短。操作多、要组合、要继承、要能被isinstance判断用类。五、数据类只想装数据时的简化封装如果类的职责主要是装一组字段可以用dataclass需要Python 3.7 及 以上自动生成__init__、__repr__、__eq__省掉一堆样板代码。# 适用于 Python 3.7from dataclasses import dataclassdataclassclass Point:x: floaty: floatp Point(1.0, 2.0)print(p) # Point(x1.0, y2.0)print(p Point(1.0, 2.0)) # True注意dataclass只是替你写样板它不会让对象变成不可变——除非加上frozenTrue。六、对照表维度函数类封装的东西行为状态 行为是否保留状态通常不保留实例各自保留调用方式f(a, b)obj.m(a)能否多态否可以继承 / 协议测试难度纯函数最易测需构造实例典型场景变换、计算、解析连接、余额、配置、状态机轻量替代——闭包 /functools.partial七、怎么选一条决策线按下面顺序问自己这份数据需要在多次调用之间保留吗不需要 → 用函数。只有一两个操作、不需要继承吗是 → 闭包也可以。主要是装字段吗是 → 用dataclass。有多个相关操作 / 需要多态 / 需要身份吗是 → 用类。常见坑点类属性当实例状态用导致所有实例共享python # ❌ items 是类属性所有实例共用同一个列表 class Basket: items [] def add(self, x): self.items.append(x)b1 Basket(); b1.add(1) b2 Basket(); b2.add(2) print(b1.items) # [1, 2]被 b2 也改了 # ✅ 在 __init__ 里给每个实例建自己的列表 class Basket: def __init__(self): self.items [] 只有一个 staticmethod 的类python # ❌ 包了一层没有任何状态还不如直接写函数 class MathUtil: staticmethod def square(x): return x * x # ✅ 模块级函数更简单 def square(x): return x * x用类当命名空间python # ❌ 类里全是常量实例化毫无意义 class Config: HOST localhost PORT 8080 # ✅ 简单场景用模块级常量或 dataclass HOST localhost PORT 8080通过实例原地修改类属性连带改了所有实例python class Basket: items [] # 类属性全类共享 b1 Basket() # ❌ 以为改的是自己那份其实动的是那个共享列表 b1.items.append(apple) # ✅ 要每个实例独立必须在 __init__ 里建 self.items class Basket: def __init__(self): self.items []__init__ 少了 selfpython # ❌ 忘记 self实例状态根本保存不下来 class A: def __init__(balance): balance 0 # ✅ 第一个参数是 self用 self. 保存 class A: def __init__(self): self.balance 0在 __init__ 里用可变默认参数python # ❌ 默认列表在所有实例间共享 class Basket: def __init__(self, items[]): self.items items # ✅ 用 None 哨兵 class Basket: def __init__(self, itemsNone): self.items [] if items is None else items想链式调用却忘了 return selfpython # ❌ 返回 None链式调用会崩 class Query: def where(self, cond): self.conds.append(cond) # ✅ 返回 self class Query: def where(self, cond): self.conds.append(cond) return self把无状态逻辑硬塞进类导致难以测试python # ❌ 需要先构造实例、设置一堆属性才能测一个纯计算 # ✅ 纯计算抽成模块级函数类只负责持有状态总结需求推荐无状态的输入输出变换函数一份状态 一两个操作闭包一份状态 一组相关操作类主要用来装字段dataclass3.7需要多态 / 身份类选择的关键就一个问题这件事需要在调用之间记住东西吗不需要就用 函数需要就用类或轻量的闭包。别为了面向对象把纯函数包进只有一个 静态方法的类里也别为了省事把本该封装的状态丢给全局变量——前者是过度设计 后者是埋雷。

相关新闻

美国商标专利注册选哪家?真正靠谱的关键只有一个

美国商标专利注册选哪家?真正靠谱的关键只有一个

这个标题看起来简单,但问的人特别多。直接回答: 美国商标专利注册没有“哪个机构好”这种选择题,因为唯一有法律效力的注册机构只有一个:美国专利商标局(USPTO) 。所有“代理机构”“律师事务所”“网络平…

2026/10/13 11:24:41 阅读更多 →
家庭WiFi卡顿?用WiFi Explorer Pro扫描信道与干扰,优化路由器设置

家庭WiFi卡顿?用WiFi Explorer Pro扫描信道与干扰,优化路由器设置

家里那台路由器已经用了三年,指示灯永远绿油油的,但实际体验完全不是那么回事。晚上八点以后,客厅电视盒子放流媒体视频卡成PPT,卧室里手机明明显示信号满格,视频通话还是会频繁掉线。这种场景很多家庭都经历过&#x…

2026/10/13 11:24:41 阅读更多 →
大模型本地微调全攻略:从硬件配置到流程避坑

大模型本地微调全攻略:从硬件配置到流程避坑

终于有人认真问“大模型能不能在自己电脑上训练”这件事了。我最近帮一个朋友调试他的本地微调项目,发现很多人对本地训练的预期是“拿来就训”,但对配套的硬件账、数据账、工具链完全没概念。所谓大模型本地训练工具,就是一套让你在自有设备…

2026/10/13 11:24:41 阅读更多 →

最新新闻

AI芯片软硬件协同设计:架构、编译器与运行时系统全解析

AI芯片软硬件协同设计:架构、编译器与运行时系统全解析

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

2026/10/13 12:07:56 阅读更多 →
AI日报制作指南:选题筛选、信源核验与内容运营

AI日报制作指南:选题筛选、信源核验与内容运营

做AI日报做到现在,我最深的感受是:AI圈从来不缺新闻,缺的是让人愿意看下去的整理方式。每天早上一睁眼,消息群里已经堆了几十条“重磅”“炸场”“史诗级更新”,但真正打开看,有一半是把旧闻改了标题&#…

2026/10/13 12:07:56 阅读更多 →
SpringBoot+Vue影院购票系统开发全解析:数据库设计、并发选座与部署实操

SpringBoot+Vue影院购票系统开发全解析:数据库设计、并发选座与部署实操

做毕设或者想练全栈的同学,在搜索引擎里肯定会刷到一类标题特别标准化的项目:某某影院购票管理系统、某某酒店预订系统、某某校园二手平台。前半段是一个具体业务场景,后半段固定是SpringBootVueMyBatisMySQL,再加一句“完整源码部…

2026/10/13 12:07:56 阅读更多 →
Windows共享打印机连不上?五层服务链修复指南

Windows共享打印机连不上?五层服务链修复指南

简介:这是一款专为Windows系统管理员及IT运维人员设计的共享打印机故障修复工具集,聚焦解决企业环境中常见的打印服务异常、连接失败、驱动丢失及Spooler服务崩溃等问题。资源包含22个文件,以8个批处理脚本(.bat)为核心…

2026/10/13 12:07:56 阅读更多 →
大白菜U盘启动工具v4.6:BIOS/UEFI双模启动盘制作指南

大白菜U盘启动工具v4.6:BIOS/UEFI双模启动盘制作指南

简介:大白菜U盘启动制作工具v4.6新年特别版是一款面向系统维护人员、装机工程师及IT爱好者的专业级启动U盘制作软件,专为解决多场景系统安装、硬盘修复与PE环境定制需求而设计。资源包共2个文件:核心可执行程序(.exe)用…

2026/10/13 12:07:56 阅读更多 →
网络安全体系方法论:可测量、可演进、可归因的实战框架

网络安全体系方法论:可测量、可演进、可归因的实战框架

简介:本资源是一份面向企业安全建设者、IT管理者及网络安全从业者的体系化方法论文档,聚焦解决‘如何构建与业务深度融合的可持续网络安全能力’这一核心问题。文档系统阐述了以IPDRR模型(识别、防护、检测、响应、恢复)为骨架的企…

2026/10/13 12:06:53 阅读更多 →

日新闻

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

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

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

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 阅读更多 →