《Effective Python》第1章 Pythonic 思维详解——深入理解流程控制中的解构利器match
《Effective Python》第1章 Pythonic 思维详解——深入理解流程控制中的解构利器match
引言
Python 3.10 引入了全新的 match
语句,它不仅是一个“类 switch”的语法结构,更是一种**结构化模式匹配(structural pattern matching)**机制。在阅读《Effective Python 3rd》的 Chapter 1, Item 9: Consider match for Destructuring in Flow Control, Avoid When if Statements Are Sufficient 后,我对 match
的设计哲学、使用场景以及潜在陷阱有了更深入的理解。
这篇笔记将从基础用法出发,结合书中示例与个人扩展,探讨 match
在流程控制中真正的价值所在。
一、从简单比较到结构解构:match
的本质是模式匹配
1.1 基础用法:像 switch 一样简洁
def take_action(light):match light:case "red":print("Stop")case "yellow":print("Slow down")case "green":print("Go!")case _:raise RuntimeError
这段代码看起来确实比 if-elif-else
更简洁,省去了重复的 ==
比较和变量引用。但如果你尝试用常量代替字符串字面值:
RED = "red"
YELLOW = "yellow"
GREEN = "green"def take_constant_action(light):match light:case RED: # ❌ 错误!这里不是比较,而是赋值print("Stop")
你会发现,这会导致一个令人困惑的行为:case RED
并不会去比较是否等于 [RED](file://D:\Workspace\Python\effective_python_3rd\src\char_01\item_09.py#L42-L42),而是会把当前 light
的值赋给变量 [RED](file://D:\Workspace\Python\effective_python_3rd\src\char_01\item_09.py#L42-L42)!
这是 match
中的“捕获模式”陷阱之一。只有当变量名带有属性访问(如 Color.RED
)或绑定到某个不可变的枚举值时,match
才能正确进行值比较。
1.2 枚举 + 点号访问:避免陷阱的推荐方式
class LightColor(enum.Enum):RED = "red"YELLOW = "yellow"GREEN = "green"def take_enum_action(light):match light:case LightColor.RED:print("Stop")case LightColor.YELLOW:print("Slow down")case LightColor.GREEN:print("Go!")case _:raise RuntimeError
通过使用 enum
和点号访问,可以安全地进行模式匹配,避免误操作。
二、真正体现 match
优势的地方:结构化解构 + 控制流
match
的核心价值在于其对数据结构的解构能力,尤其是在处理异构结构的数据(heterogeneous data structures)和半结构化数据(semi-structured data)时。
2.1 解构元组表示的二叉树
假设我们有如下结构的二叉树:
my_tree = (10, (7, None, 9), (13, 11, None))
每个节点是三元组 (pivot, left, right)
,叶子节点直接以值表示。
使用 if
实现查找函数:
def contains(tree, value):if not isinstance(tree, tuple):return tree == valuepivot, left, right = treeif value < pivot:return contains(left, value)elif value > pivot:return contains(right, value)else:return value == pivot
使用 match
实现查找函数:
def contains_match(tree, value):match tree:case pivot, left, _ if value < pivot:return contains_match(left, value)case pivot, _, right if value > pivot:return contains_match(right, value)case (pivot, _, _) | pivot:return pivot == value
可以看到,match
的版本:
- 避免了显式的
isinstance
判断; - 自动完成了元组的解包;
- 使用了 guard expression(守卫表达式)来进行额外条件判断;
- 使用
|
表达“或”关系,使代码更简洁; - 整体逻辑更清晰,代码更紧凑。
2.2 使用自定义类进行结构匹配
如果我们把树节点换成类的形式:
class Node:def __init__(self, value, left=None, right=None):self.value = valueself.left = leftself.right = right
那么 match
同样可以轻松应对:
def contains_match_class(tree, value):match tree:case Node(value=pivot, left=left) if value < pivot:return contains_match_class(left, value)case Node(value=pivot, right=right) if value > pivot:return contains_match_class(right, value)case Node(value=pivot) | pivot:return pivot == value
这里,match
不仅自动进行了类型检查(isinstance
),还能提取对象属性并用于守卫判断,极大简化了逻辑。
三、处理半结构化数据:JSON 反序列化中的 match
应用
在现代应用中,我们经常需要解析 JSON 数据,并将其映射为特定类型的对象。例如:
{"customer": {"last": "Ross", "first": "Bob"}}
{"customer": {"entity": "Steve's Painting Co."}}
我们可以使用 match
来优雅地实现反序列化逻辑:
@dataclass
class PersonCustomer:first_name: strlast_name: str@dataclass
class BusinessCustomer:company_name: strdef deserialize(data):record = json.loads(data)match record:case {"customer": {"last": last_name, "first": first_name}}:return PersonCustomer(first_name, last_name)case {"customer": {"entity": company_name}}:return BusinessCustomer(company_name)case _:raise ValueError("Unknown record type")
这种写法的优势在于:
- 结构清晰,一眼看出不同格式的匹配规则;
- 支持嵌套结构的匹配;
- 提取字段的同时完成赋值;
- 类型安全强于传统的
dict.get()
方式。
四、总结:什么时候该用 match
?什么时候不该用?
✅ 推荐使用 match
的场景:
- 数据结构具有层级性、嵌套性(如树、图、JSON);
- 需要同时进行类型判断和字段提取;
- 分支逻辑与结构密切相关;
- 需要统一处理多种结构形式(如多个类/字典/元组);
- 使用守卫表达式进行复杂的条件控制。
❌ 不推荐使用 match
的场景:
- 简单的值比较(如字符串、整数);
- 分支逻辑与结构无关;
- 多个
case
分支只是对同一个变量做不同的值比较; - 对性能要求极高,且
match
解构带来了额外开销。
五、结语
通过阅读《Effective Python 3rd》的第 9 条目,我深刻认识到:match
并不是一个简单的语法糖,而是一种新的编程思维方式。它鼓励我们用结构化的思维去描述问题,而不是仅仅靠一堆 if-else
堆砌逻辑。
掌握 match
,意味着你不仅能写出更简洁的代码,更能理解数据与逻辑之间的深层联系。这正是现代软件工程所追求的方向。
后续我会继续分享更多关于《Effective Python》精读笔记系列,参考我的代码库 effective_python_3rd,一起交流成长!
相关文章:
《Effective Python》第1章 Pythonic 思维详解——深入理解流程控制中的解构利器match
《Effective Python》第1章 Pythonic 思维详解——深入理解流程控制中的解构利器match 引言 Python 3.10 引入了全新的 match 语句,它不仅是一个“类 switch”的语法结构,更是一种**结构化模式匹配(structural pattern matching)…...
【氮化镓】横向GaN 器件注入隔离区的电场相关载流子传输特性
文章的关键结论和发现如下: 在GaN横向功率器件中,注入隔离区的载流子传输具有明显的电场依赖性,且其泄漏电流和击穿特性主要由注入的GaN区域决定,与缓冲层和UID GaN层的性质关系不大。 载流子传输机制随电场强度变化呈现三个不同区域:低电场下为欧姆传导,符合变程跃迁(V…...
电子电器架构 --- 借力第五代架构,驱动汽车产业创新引擎
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界…...
【ROS2】通信部署概述(以话题(Topic)通信为例)
写在前面 很多内容参考了赵虚左老师的ROS2教程 概念说明 工作空间:相当于一个项目,比如一台机械臂,或者一个机器人 功能包:相当于一个项目中的一台设备,如电机、雷达、相机等 大概构建流程 以话题通信机制为例 创…...
1.8 梯度
(知识体系演进逻辑树) 一元导数(1.5) │ ├─→ 多元偏导数(1.6核心突破) │ │ │ └─解决:多变量耦合时的单变量影响分析 │ │ │ ├─几何:坐标轴切片切线斜率…...
Pycharm中No Conda enviroment selected
最近在学习Anaconda,换了台新电脑重新安装PyCharm和Anaconda后,打算创建环境,创建后发现找不到刚刚在Anaconda中创建的环境,经过不断摸索后找到解决方案 将选择的路径从Anaconda目录下的python.exe换成Anaconda\Library\bin下的c…...
continue通过我们的开源 IDE 扩展和模型、规则、提示、文档和其他构建块中心,创建、共享和使用自定义 AI 代码助手
一、软件介绍 文末提供程序和源码下载 Continue 使开发人员能够通过我们的开源 VS Code 和 JetBrains 扩展以及模型、规则、提示、文档和其他构建块的中心创建、共享和使用自定义 AI 代码助手。 二、功能 Chat 聊天 Chat makes it easy to ask for help from an LLM without…...
关于读写锁的一些理解
同一线程的两种情况: 读读: public static void main(String[] args) throws InterruptedException {ReentrantReadWriteLock lock new ReentrantReadWriteLock();Lock readLock lock.readLock();Lock writeLock lock.writeLock();readLock.lock();S…...
Ubuntu网络部署LNMP环境
目录 1. 安装nginx 2. 安装mysql 3. 安装PHP 4. 配置nginx,修改默认配置文件 5. 配置PHP 1. 安装nginx apt install -y nginx#开启 systemctl start nginx#浏览器访问页面 192.168.180.200:80#nginx网页html存放路径 ls /usr/share/nginx/#查看nginx版本号 ng…...
榜单按行显示
手机芯片_SoC天梯榜_安兔兔跑分排行_安兔兔 我只关注 骁龙7Gen1,天玑7300,骁龙6Gen1,天玑900 除了 50,64,75,86 行都隐藏。 var uls document.getElementsByClassName(newrank-c); var s 50,64,75,86; var sa s.split(,); for (var i0…...
DVWA在线靶场-xss部分
目录 1. xxs(dom) 1.1 low 1.2 medium 1.3 high 1.4 impossible 2. xss(reflected) 反射型 2.1 low 2.2 medium 2.3 high 2.4 impossible 3. xss(stored)存储型 --留言板 3.1 low 3.2 medium 3.3 high 3.…...
将本地文件上传到云服务器上
使用 SCP 命令(最常用) # 基本语法 scp [本地文件路径] [用户名][服务器IP]:[目标路径]# 示例:上传单个文件 scp /path/to/local/file.txt root192.168.1.100:/path/to/remote/# 上传整个目录 scp -r /path/to/local/directory root192.168.…...
关系实验课--笛卡尔积
import sympy as sym a, b sym.symbols(a b) # 定义符号 a 和 b A sym.FiniteSet(a,b) # 创建包含 a 和 b 的有限集合 B sym.FiniteSet(1,2,3,4) AxB sym.cartes(A,B) # 返回迭代器。迭代器不会直接显示内容,而是需要手动遍历或转换为其他数据类型(如…...
从0开始学习大模型--Day07--大模型的核心知识点
AI常见名词 知识库 分为传统知识库与AI知识库,前者是单纯的存储各个领域的知识,后者则是与LLM结合,使AI系统能够更好地利用本地知识来响应查询和执行任务。比如,假如公司新来了个维修人员,他可以直接调用AI知识库去学…...
无线定位之 二 SX1302 网关源码 thread_down 线程详解
前言 笔者计划通过无线定位系列文章、系统的描述 TDOA 无线定位和混合定位相关技术知识点, 并以实践来验证此定位系统精度。 笔者从实践出发、本篇直接走读无线定位系统关键节点、网关 SX1302 源码框架,并在源码走读过程 中、着重分析与无线定位相关的PPS时间的来龙去脉、并在…...
MINIX 1.0 文件系统的实现(C/C++实现)
MINIX 1.0 文件系统简介: Linux 0.11操作系统启动时需要加载一个根目录,此根目录使用的是MINIX 1.0文件系统,其保存在硬盘的第一个分区中。Linux 0.11操作系统将硬盘上的两个连续的物理扇区(大小为512字节)做为一个物理…...
Spring Data Elasticsearch 中 ElasticsearchOperations 构建查询条件的详解
Spring Data Elasticsearch 中 ElasticsearchOperations 构建查询条件的详解 前言一、引入依赖二、配置 Elasticsearch三、创建模型类(Entity)四、使用 ElasticsearchOperations 进行 CRUD 操作1. 保存数据(Create)2. 获取数据&am…...
keil 解决 Error: CreateProcess failed, Command: ‘XXX\ARM\ARMCC\bin\fromelf.exe
参考文章链接: https://blog.csdn.net/qq_39172792/article/details/145499880 自己的: D:\Program Files\keil529\Keil_v5\ARM\ARMCLANG\bin\fromelf.exe --bin -o …/…/firmware_bin/L.bin ./Object/L.axf...
针对面试-mysql篇
1.如何定位慢查询? 1.1.介绍一下当时产生问题的场景(我们当时的接口测试的时候非常的慢,压测的结果大概5秒钟)),可以监测出哪个接口,最终因为是sql的问题 1.2.我们系统中当时采用了运维工具(Skywalkin就是2秒,一旦sql执行超过2秒…...
HNUST软件测试B考前最终复习
最近根据各个专业整理的考试重点,这两天总结出了以下内容,并附上了我自己复习的一些记忆小技巧,供大家参考,大家就图一乐。希望对你们的复习有所帮助,预祝大家考试顺利,加油! 本次考试和去年的题…...
网络编程epoll和udp
# epoll模型核心要点## 1. epoll核心概念### 1.1 高效IO多路复用- 监视列表与激活列表分离- 内核使用红黑树存储描述符- 边缘触发模式(EPOLLET)支持### 1.2 事件触发机制- **水平触发(LT)**:- 默认模式,类似select/poll- 数据未读完持续触发事件- **边缘…...
【速写】use_cache参数与decode再探讨
序言 纳什最近指出一个小细节,比如在Qwen系列模型中,两个special token: eos_token(<|im_end|>): 151645(im_end 中的 im 指的是 instruct message)pad_token(<|endoftext|>): 151643。 这是很有趣的事…...
智能网联汽车“内外协同、虚实共生”的通信生态
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界…...
《Python星球日记》 第64天:NLP 概述与文本预处理
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、NLP 简介1. 什么是自然语言处理?NLP 的应用场景: 2.…...
Java中堆栈
文章目录 Java中堆栈1. 栈(Stack)特点示例 2. 堆(Heap)特点示例 3. 核心区别4. 常见问题5. 内存可视化示例内存布局示意图: 总结 Java中堆栈 在 Java 中,“堆栈” 通常指的是堆(Heap࿰…...
模块化PCB设计中联排半孔的应用
随着电子产品的快速发展,高密度、多功能和小型化已成为未来的趋势。电路板上的元件几何指数在增加,而PCB尺寸却越来越小,因此需要与支撑板做配合。如果用助焊剂将圆孔焊接到母板上,由于圆孔体积较大,会产生冷焊&#x…...
xss-lab靶场4-7关基础详解
前言: 仅作为练习,复盘 推荐html在线运行平台,弹窗标签可以在平台运行,看语句是否能正常弹窗 HTML/CSS/Javascript在线代码运行工具 | 菜鸟教程 内容: 第四关 打开一看,输入<script>alert(1)&l…...
【Linux】进程状态、优先级、切换和调度
目录 一、传统操作系统进程状态 (一)什么是状态 (二)运行状态 (三)阻塞状态 (四)挂起状态 二、Linux进程状态 (一)进程状态 (二ÿ…...
软件测试基础知识详解
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 1、黑盒测试、白盒测试、灰盒测试 1.1 黑盒测试 黑盒测试 又叫 功能测试、数据驱动测试 或 基于需求规格说明书的功能测试。该类测试注重于测试软件的功能性需…...
【WordPress博客AI内容辅助生成/优化工具箱插件下载无标题】
主要功能 AI内容生成/优化 使用AI模型生成或优化段落内容 支持撤销和模型切换 AI自动评论 智能分析文章内容生成相关评论 可配置的评论数量和随机调度 生成评论回复的概率(评论数>10时) 可能以特定概率包含表情符号 AI标签提取 从文章内容自动提取相关标签 新标签可自动生…...
js 画立方体软件开发日记2
我不懂但我大为震惊 重开几次又回去了 这说明之前的操作无效 搞了个调试当前文件 导出模块有问题,跑显示没事 启动太慢,重构吧 ----------------------------------------------- 把那些鬼相机投影代码删了就有4s了 按钮全删了,还是卡&…...
element plus el-table多选框跨页多选保留
一、基础多选配置 通过 type“selection” 开启多选列,并绑定 selection-change 事件获取选中数据 <template><el-table :data"tableData" selection-change"handleSelectionChange"><el-table-column type"selection&qu…...
智能家居“心脏“升级战:GD25Q127CSIG国产芯片如何重构家庭物联生态
在智能家居设备出货量突破10亿台的2023年,家庭网关正经历着前所未有的技术革新。作为连接云端与终端设备的中枢神经,智能网关的存储芯片选择直接决定着整个智能生态系统的运行效率。在这场技术升级浪潮中,兆易创新GD25Q127CSIG串行闪存芯片主…...
智能枪弹柜管理系统|智能枪弹柜管理系统LK-QDG-Q20型
是一种用于存放枪支弹药的智能化设备,主要应用于涉枪单位,以下将从其功能特点、系统组成、优势等维度展开介绍: 功能特点 身份识别功能:采用多种生物识别技术,如指纹识别、指静脉识别、虹膜识别、人脸识别、声纹识别等…...
bootstrap table 添加跳转到指定页的功能(仅自己可见)
Table回调方法中,添加input和button至Table下方(Table页渲染结束后执行) (input用来输入页码,button执行跳转) function ajaxRequestExtends(data){$(".page-list").append("<input idp…...
rufus+Ubuntu 18.04 镜像
参考:https://blog.csdn.net/Li060703/article/details/106075597 Rufus 官网: https://rufus.ie/zh/ 步骤 安装U盘做好后插在主板io的USB口上,启动阶段用F2或DEL打断进bios,bios里面指定从安装U盘来启动,里面的B…...
基于事件驱动和策略模式的差异化处理方案
一、支付成功后事件驱动 1、支付成功事件 /*** 支付成功事件** author ronshi* date 2025/5/12 14:40*/ Getter Setter public class PaymentSuccessEvent extends ApplicationEvent {private static final long serialVersionUID 1L;private ProductOrderDO productOrderDO;…...
【运维】MacOS蓝牙故障排查与修复指南
在日常使用macOS系统过程中,蓝牙连接问题时有发生。无论是无法连接设备、连接不稳定还是蓝牙功能完全失效,这些问题都会严重影响我们的工作效率。本文将分享一些实用的排查方法和修复技巧,帮助你解决macOS系统上的蓝牙故障。 问题症状 常见…...
linux小主机搭建自己的nas(三)docker安装nextcloud
小主机用的TF卡,不可能把nas的数据放在卡上,所以我买了个2T的移动硬盘 1.挂载移动硬盘 查找硬盘 lsblk # 或 fdisk -l 创建挂载点 sudo mkdir -p alon_ssd 查看硬盘文件系统,文件系统类型一会儿设置挂载用 sudo blkid /dev/sda1 开机自动挂载&…...
Go语言:json 作用和语法
在 Go 语言中,JSON 字段(也称为 JSON Tag)是附加在结构体字段上的元数据,用于控制该字段在 JSON 编码(序列化)和解码(反序列化) 时的行为。它的语法是: type StructName…...
mageia系统详解
Mageia 是一个由社区驱动的 Linux 发行版,源自 Mandriva Linux(原 Mandrake Linux),以用户友好性和强大的系统工具著称。它继承了 Mandriva 的易用性传统,同时专注于稳定性和社区协作。以下从历史背景、技术架构、系统…...
六、STM32 HAL库回调机制详解:从设计原理到实战应用
STM32 HAL库回调机制详解:从设计原理到实战应用 一、回调机制的本质与设计目标 在STM32 HAL库中,回调机制是实现异步事件处理的核心设计模式。它通过弱定义函数用户重写的方式,将硬件事件(如数据传输完成、定时器溢出等…...
USB传输模式
USB有四种传输模式: 控制传输, 中断传输, 同步传输, 批量传输 1. 中断传输 中断传输一般用于小批量, 非连续的传输. 对实时性要求较高. 常见的使用此传输模式的设备有: 鼠标, 键盘等. 要注意的是, 这里的 “中断” 和我们常见的中断概念有差异. Linux中的中断是设备主动发起的…...
lenis滑动插件的笔记
官网 lenis - npm 方法一:基础判断(推荐) 通过 Lenis 自带的 scroll 和 limit 属性直接判断: const lenis new Lenis()// 滚动事件监听 lenis.on(scroll, ({ scroll, limit }) > {const distanceToBottom limit - scroll…...
【网络安全】SQL注入
如果文章不足还请各位师傅批评指正! 想象一下,你经营着一家咖啡店,顾客可以通过店内的点单系统下单。这个系统会根据顾客的输入,向后厨发送指令,比如“为顾客A准备一杯拿铁”。 然而,如果有个不怀好意的顾客…...
window server 2012安装sql server2008 r2
执行sql server2008 r2安装目录下的setup 选择运行程序而不获取帮助 然后就是让人绝望的 只能先搞这个了,F*微软,自家软件不让正常安装 打开服务器管理器->添加角色和功能->选择Web 服务(IIS)->添加.NET Framework3.5 然…...
uni-app学习笔记五--vue3插值表达式的使用
vue3快速上手导航:简介 | Vue.js 模板语法 插值表达式 最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法 (即双大括号): <span>Message: {{ msg }}</span> 双大括号标签会被替换为相应组件实例中 msg 属性的值。同…...
RuoYi 中使用 PageUtils.startPage() 实现分页查询的完整解析
文章目录 一、PageHelper 简介与基本用法使用方式如下: 二、Mapper 接口返回类型对分页的影响1. 返回 Page<T> 类型(推荐)2. 返回 List<T> 类型(不推荐) 三、解析RuoYi 是如何使用 PageUtils.startPage()1…...
【番外】02:Windows 编译带 DNN_CUDA 功能的 OpenCV 动态链接库
文章目录 1. 环境准备2. 兼容性说明3. 算力查询4. 编译步骤5. 网盘资料 提示: 如果读者因网络环境受限,无法正常下载与本文相关的软件安装包、压缩包,以及编译时的依赖文件,可以从文章最后提供的网盘链接下载资源。 1. 环境准备 …...
Java详解LeetCode 热题 100(14):LeetCode 56. 合并区间(Merge Intervals)详解
文章目录 1. 题目描述2. 理解题目3. 解法一:排序 一次遍历法3.1 思路3.2 Java代码实现3.3 代码详解3.4 复杂度分析3.5 适用场景 4. 解法二:双指针法4.1 思路4.2 Java代码实现4.3 代码详解4.4 复杂度分析4.5 与解法一的比较 5. 解法三:TreeMa…...