news 2026/9/28 4:44:04

枚举进阶:90%代码错误的终结者

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
枚举进阶:90%代码错误的终结者

这里介绍的是进阶技巧, 这些技巧可以让你提交的代码里面所包含的低级错误数量大幅度减少, 降低的幅度能够达到百分之九十。

在开发的这个过程里头, 存在一种特性的样子, 这种特别的程度非常微小, 但是它却能够产生出那种特别巨大的能量, 如果能把这个特性给使用得适当得当的话, 它就可以直接把一整类编程漏洞的现象给消除掉。遗憾的是, 大多数的开发工作者只是听说过有这么一个事情的存在, 实际上却并没有把这个特性给真正地用好。

假如你曾经由于误写了一个字母, 或者是因为在不一样的场所对同一状态的称呼没能保持统一状况相同, 使得编写的程序出现了运行时的错误情况, 那么这篇文档里头所展示的关于枚举类型的那些更加深入使用的技巧办法方面内容, 就是可以帮助你提高自己编代码的质量层次, 并且在职业发展过程中成为一位更资深技术人员阶段所必须经过的一个非常重要环节。

一、 潜伏在代码里的“字符串陷阱”。

当写代码的时间达到足够漫长的程度之后, 你一定会见过那种情况, 甚至说不定还亲手写过类似这样的逻辑呢。

if status == "completed":

...

elif status == "Complete":

...

elif status == "done":

...

这个代码最让人害怕的地方就在于它根本就不会出现报错的情况。因为没有任何一个异常会被抛出来, 所以从表面看起来程序是完全运行正常的。但是实际上业务逻辑已经悄悄地偏离了预想的轨道。导致生产环境可能正处于一种隐形的崩溃边缘之中。

这个问题的真正起因, 其实并不是你的逻辑思维出了毛病, 而是因为你那个做法里, 使用了伪装成状态的字符串。

咱们来好好捋一捋, 为什么很多人总觉得常量和字符串这些东西挺危险的。

在诸多项目的初始阶段, 参与者为了能够迅速达成目标, 往往会采取这样一种方式来对常量进行定义。

PENDING = "pending"

ACTIVE = "active"

CANCELLED = "cancelled"

乍一看, 这个情况显得很整齐并且很有序, 可是伴随着项目规模的逐渐扩大, 一些潜在的危险和问题也接着来到了面前。

字符串所表达出来的含义是巧合, 但是我们这边真正需要表达的含义是意图, 正因为存在这种差异, 所以才决定了必须把枚举类型给引入进来加以使用。

二、 所谓的基础用法这个概念, 它不仅仅只是起到给常量进行分类的作用。

在大多数开发人员的认识里面, 他们对于枚举这个概念的理解, 往往只是简单地把它看作是一种将一大堆常量进行打包处理的方式:

from enum import Enum

class Status(Enum):

PENDING = "pending"

ACTIVE = "active"

CANCELLED = "cancelled"

这确实比没有经过处理的杂乱字符串要好, 不过要是就到此为止, 那你就完全错过了枚举最厉害的地方, 在那些经验丰富的开发者看来, 枚举压根就不只是一堆常量的集合, 它们是带有具体功能的类型。

这便是需要我们进行深入探讨的主要内容所在, 即务必将枚举视作领域对象来加以考量和处理。

三、 进阶的这个技巧就是去给枚举加上一种生命力, 第一个小项是关于怎样把逻辑内容封装并放入到枚举的内部之中。

核心心法是, 要枚举应该使用的编码规则, 而不仅仅是数值。

千万千万不要在业务的代码里头, 到处散落那些判断的逻辑, 比如说像是什么如果等于的那个冒号括号那样子的东西。相反的方面讲嘛, 你就应该把这些叫做是否允许访问的规则, 直接把它写进那个枚举里面去。

from enum import Enum

class UserStatus(Enum):

PENDING = "pending"

ACTIVE = "active"

SUSPENDED = "suspended"

DELETED = "deleted"

def can_login(self) -> bool:

# 只有活跃用户可以登录

return self in {UserStatus.ACTIVE}

def is_terminal(self) -> bool:

# 账号是否已进入不可逆的最终状态

return self in {UserStatus.DELETED}

这样做一改之后, 你的业务逻辑将会变得非常明确。

if user.status.can_login():

authenticate(user)

这代码读起来就像英语短句一样自然, 根本不需要额外注释去说明, 规则被统一锁定在枚举定义里头, 维护起来觉得特别方便。

2. 实现无缝的序列化

许多人拒绝使用枚举的一个理由是, 他们觉得枚举会破坏 JSON 序列化这个过程, 会导致报错, 而这种错误情况非常令人烦躁。

实际上, 解决这个问题的方法是非常简单的, 我们只需要让那个枚举同时去继承字符串类型就可以了。

from enum import Enum

class OrderStatus(str, Enum):

CREATED = "created"

PAID = "paid"

SHIPPED = "shipped"

使用这种形式, PAID 本身就是一个字符串。不管是在调用json.dumps()的时候, 还是和在Flask这些框架里面跟前端进行通信的时候, 它都能够像普通的字符串一样去完美地工作起来。同时, 它还把枚举所具备的所有类型上的优势都给保留下来了。

3. 在入口的位置把那些不符合规定的情况给拦下来。

比起在代码的非常底层的地方编写很多用来保护性的判断条件语句, 去检查字符串是否符合规则这种办法, 我们完全可以选择另外一种更为直接的方式, 就是在数据真正进入整个系统运作的那一个边界层面,立刻对它进行类型或者形态上的强行转换和调整。

# 假设 request_data 来自外部 API

status = OrderStatus(request_data["status"])

把那个传入的值跟定义好的枚举范围来做一下对比, 一旦发现它并不在那个范围内的话, 程序就会马上就把一个异常给抛出来, 像这样一种让错误早点失败的办法, 就是能够去防止那些不合法的数据去污染接下来的业务逻辑的。

四、 在现代生活当中, 这被看作是黄金这样的一种非常完美的组合方式。

如果你使用的是 3.10 或更高版本, 那么枚举与模式匹配合在一起使用, 这种情况简直可以说是艺术。

match order.status:

case OrderStatus.CREATED:

prepare_payment()

case OrderStatus.PAID:

ship_order()

case OrderStatus.CANCELLED:

refund()

这种写法相比起一长串的 if、elif 代码段, 会更加的安全, 也会更加的容易阅读。它强制要求开发人员必须要去考虑所有的可能状态的一个全面覆盖, 这样一来, 就能使得整体的一个代码结构变得愈发的紧密, 以及严肃。

五、 替代布尔值的最佳实践

当你准备去写下等于真这个代码的时候, 请你停下来认真思考一下, 这里所提到的活跃到底具体是指的什么意思。

在实际情况中, 布尔值通常会掩盖掉真正的意图。等到业务发展起来之后, 本来只存在“是”和“否”这两种明确状态的情况, 慢慢地就会变成有好多种情况的复杂状态。所以, 我们建议大家使用枚举类型来替换那些意思不太清楚的布尔值:

class AccountState(Enum):

TRIAL = "trial" # 试用期

ACTIVE = "active" # 正式激活

GRACE_PERIOD = "grace" # 宽限期

CLOSED = "closed" # 已关闭

强制让开发者用枚举的方式来表达状态, 这样做把那种因为二元判断而产生的歧给彻底消除掉了。

六、 关于避开那些潜在坑洼的一个指南,对于那些不应该去犯下的错误方面, 这里有一个说明。

就算是一个很有经验的开发者, 在使用枚举这个功能的时候, 也特别容易不小心踩进这几个坑里面去。

七、 总结

判定一个开发者的高下, 只需要观察他在处理状态逻辑时的具体表现就完全足够了。

初学者在写代码的时候, 他们最关心的事情是这个代码“能不能跑通”, 而资深的开发人员去编写代码的时候, 他们关心的是这个代码“会不会在悄悄地坏掉”。这里去使用枚举技术, 并不是为了能够炫耀自己的技巧, 而是为了去建立一种有效的防御机制。

通过这种机制, 可以将那些在运行时出现的、不被人发现的隐形 bug 转化为显性的报错信息。另外, 这也能够将那些看起来很混乱的业务逻辑收纳到清晰的结构模型中。

你应当停止让那些杂乱的字符串来掌控你的系统。建议你试着把相关的逻辑搬进枚举类型里去进行整理, 通过这一番操作之后, 你就会明显地发现原先的程序代码能够变得前所未有的强健可靠, 同时也能变得更加容易阅读理解。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 4:44:00

小白程序员必看:Agent开发与大模型开发的区别及入行指南

本文详细对比了大模型算法工程师与agent开发工程师的薪资待遇、工作内容、学习门槛及发展前景。大模型算法岗薪资高但门槛极高,而agent开发岗入门相对简单,更适合小白和程序员。随着AI技术的发展,agent开发将成为未来的趋势,具备落…

作者头像 李华
网站建设 2026/9/28 4:43:36

GemeOpen 86型零火智能开关-三开-WiFi版 (型号:GSCW3B) - 开发者指令

86型零火智能开关-三开-WiFi版 (型号:GSCW3B) - 开发者指令 产品基本描述 产品主要特点 WiFi网络,三路控制 AC110v-250v宽电压输入 单路最大负载800W 开发者文档 https://www.smart-bird.cn/doc/product/GSCWB/device/GSCW3B/command 产品电气参数…

作者头像 李华
网站建设 2026/9/28 4:43:17

人体行为数据集 跌倒检测数据集 摔倒识别 AI图像识别

室内跌倒目标检测数据集 数据集概述室内跌倒目标检测数据集,通过室内监控摄像头采集,聚焦室内场景下的人员跌倒行为检测,共约 7000 张图像,全部完成人工标注,适用于老人看护、居家安全监测、异常行为识别等视觉任务&am…

作者头像 李华
网站建设 2026/9/28 4:42:28

JavaSE/EE/ME终极解析:一文搞懂三者区别

你是否在很多时候都见到了Java SE、Java EE、Java ME这几个词, 每一次你觉得自己好像认识它们了, 但却说不清楚它们到底有哪些具体的区别?你是否遇到过有人告诉你学好Java就是学好Java SE的情况, 可是转个弯你就在网上看到了招聘的要求上面写着需要具备精通Java EE的能力? 更…

作者头像 李华
网站建设 2026/9/28 4:42:19

Python凭借丰富的第三方库生态(如pandas、matplotlib、reportlab等),为自动化数据分析与报告生成提供了高效解决方案

在数字化办公时代,数据分析与报告生成是高频需求场景。传统手工处理Excel、撰写Word报告的方式存在效率低、易出错、重复劳动多等问题。Python凭借丰富的第三方库生态(如pandas、matplotlib、reportlab等),为自动化数据分析与报告…

作者头像 李华