10、Python之写出更加Pythonic的代码:unpacking拆包机制

引言

有些小伙伴有其他编程语言的学习、使用的经验,然后迁移到Python。一般会比完全的新手小白,更快速地把Python用起来。这是他们的优势,但也是他们的劣势。
之所以这么说,是因为从其他编程语言带过来的,除了相通的编程思维、框架性的东西,还有编程语言的使用习惯。
而这些其他编程语言中的使用习惯,就会导致他们写出来的Python代码不是那么的Pythonic,当然,这是一种感觉。
虽说我们首要追求的是能用、够用。但是,偶尔也要稍微留意一下。就好像学习英语一样,虽然不追求能操着一口正宗的英伦腔,但也不应该对自己的chinglish迷之自信。
此外,故步自封于其他编程语言中的编程习惯,也可能限制我们更加灵活、便捷地发挥Python中的强大特性。

变量值交换

其他语言中,如果需要交换两个变量,通常需要引入一个中间变量,比如:

a = 5
b = 10
c = b
b = a
a = c

在Python中还这样写,就显得有些冗余、不够地道了。
其实,在Python中有一种更加简便的写法:

x = 5
y = 10
x, y = y, x

不需要引入中间变量,直接完成变量值的交换。我看有些地方把Python中的这种变量值交换,称之为unpacking机制。所以,我在今天的这篇讲解unpacking机制的文章中提到了这一点。

但是,也许是Python不同版本、Python解释器实现的差异,在我的Python3.11、CPython解释器的环境下,查看对应的字节码,发现并没有用到unpacking机制,而是Python中提供了一个用于进行栈顶两个值交换的swap指令。对应的字节码指令及解释,如下图所示:感兴趣的可以自行查看自己环境中变量值交换的实现。

基础unpacking机制

接下来,说回今天的主题,unpacking机制。
既然是unpacking,有些地方翻译为拆包,自然首先要有包可拆。这里所谓的拆包,其实是针对容器/集合类型的数据结构来说的。

通常情况下,我们把一个列表、元组或者是字典中的元素取出来,可以使用下标索引的方式。
比如,有如下场景:
我们有一些人员信息存放在一个列表中,每个列表元素是一个元组,元组中的元素,分别是姓名、年龄、性别。
现在,我们需要遍历人员信息的这个列表,然后将人员信息进行格式化打印输出。
使用下标索引的方式,可以这样实现:

persons = [('张三', 18, '女'), ('小红', 23, '男')]
for p in persons:name = p[0]age = p[1]gender = p[2]print(f"姓名: {name}, 年龄: {age}, 性别: {gender}")

但是,这样的写法,不够地道,没有使用Python给我们提供的更加好用的写法。
接下来,我们用unpacking的方式重新写一下:

# unpacking
persons = [('张三', 18, '女'), ('小红', 23, '男')]
for p in persons:name, age, gender = pprint(f"姓名: {name}, 年龄: {age}, 性别: {gender}")

这样写下来,用到了Python中的unpacking,首先代码行数减少了。
是否真的应用到了unpacking机制,还是说跟变量值交换一样,也是人云亦云,我们可以看下对应的字节码序列:

字节码指令序列的其他指令可以不用关心,我们重点看源码第4行的对应指令序列,可以看到:
1、确实触发了unpacking机制;
2、UNPACK_SEQUENCE指令,用于将栈顶的集合变量进行拆包的操作,拆为多少个,指令有一个操作数,此时是3,由操作数决定;
3、拆包指令实现的结果是,栈顶集合变量出栈,按照操作数拆分,然后依次入栈。

unpacking的机制,看似好用,但是,细心的你,可能立马会发现一个问题,如果集合中元素有很多个,此时,我们只需要其中的一部分,怎么办呢。

解决的方法,就是我们在前面的文章中提到过的占位符_的用法。
比如,我们当前,只需要姓名、性别,可以这样改写:

# unpacking
persons = [('张三', 18, '女'), ('小红', 23, '男')]
for p in persons:name, _, gender = pprint(f"姓名: {name}, 性别: {gender}")

所有我们不需要的元素,都可以用占位符进行舍弃,但是,占位符_只是省去了我们给变量取名的麻烦,不需要的元素比较多的时候,似乎还是不太方便,反而不如索引操作方便,好在Python中提供了对应的解决方案。

扩展的unpacking

的变量,在Python中为可扩展的变量。
如下,为带
的unpacking的写法:

# * unpacking
persons = [('张三', 18, 190, '女'), ('小红', 23, 165, '男')]
for p in persons:name, *others, gender = pprint(others)print(type(others))print(f"姓名: {name}, 性别: {gender}")

代码中,会将除了name接收的第一个元素,以及gender接收的最后一个元素,之外的所有元素,封装为一个列表,由others接收。
从对应的字节码,可以看出有些不同:

首先,翻译为字节码指令序列时,多了EXTENDED_ARG指令,用于扩展变量others;其次拆包的指令,从之前的UNPACK_SEQUENCE变成了UNPACK_EX。

注意,关于带星号定义的可扩展变量,可以理解为不定长列表,可以接收零个或者多个值,后续在函数的定义中也会用到。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/43769.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第十八节 LLaVA如何按需构建LORA训练(视觉、语言、映射多个组合训练)

文章目录 前言一、基于llava源码构建新的参数1、添加lora_vit参数2、训练命令脚本设置二、修改源码,构建lora训练1、修改源码-lora训练2、LLM模型lora加载3、VIT模型加载4、权重冻结操作5、结果显示三、实验结果前言 如果看了我前面文章,想必你基本对整个代码有了更深认识。…

Raylib 实现超大地图放大缩小与两种模式瓦片地图刷新

原理: 一种刷新模式: 在宫格内整体刷新,类似九宫格移动到边缘,则九宫格整体平移一个宫格,不过这里是移动一个瓦片像素,实际上就是全屏刷新,这个上限是 笔记本 3060 70帧 100*100个瓦片每帧都…

数据库之MQL

1,查询所有 mysql> select * from grade;2, mysql> select id,firstname,lastname from grade;3, mysql> select firstname,lastname from grade where id > 4;4, mysql> select * from grade where sex f;5&…

odoo17 常见升级问题

通用问题 模型名变更 字段变更 方法名变更 方法参数变更 xml数据结构定义变化 xml的id变更 view视图变化,导致xpath路径出差 template结构变化,,导致xpath路径出差,或者id不存在 升16问题 前端owl的架构变化 升17问题 前端 标…

什么,有狗快跑!慢着,这次手把手教你怎么过安全狗!(sql注入篇)

前言 在记忆里上次绕安全狗还是在上次,开开心心把自己之前绕过狗的payload拿出来,发现全部被拦截了,事情一下子就严肃起来了,这就开整。 环境 本次环境如下sqli-lab的sql注入靶场 网站安全狗APACHE版V4.0版本的最高防护等级绕过…

秋招Java后端开发冲刺——并发篇2(ThreadLocal、Future接口)

本文对ThreadLocal类和Future接口进行了总结概括,包括ThreadLocal类的原理、内存泄露等问题,和Future接口的使用等问题。 一、ThreadLocal 1. 介绍 ThreadLocal(线程局部变量)是Java中的一个类,线程通过维护一个本地…

一文带你彻底搞懂什么是责任链模式!!

文章目录 什么是责任链模式?详细示例SpingMVC 中的责任链模式使用总结 什么是责任链模式? 在我们日常生活中,经常会出现一种场景:一个请求需要经过多个对象的处理才能得到最终的结果。比如,一个请假申请,需…

STM32智能仓库管理系统教程

目录 引言环境准备智能仓库管理系统基础代码实现:实现智能仓库管理系统 4.1 数据采集模块 4.2 数据处理与控制算法 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景:仓库管理与优化问题解决方案与优化收尾与总结 1. 引言 智能仓库管理系统通…

藏汉翻译通作为翻译软件的优势有哪些?

藏汉翻译通作为一款专业的藏汉双语翻译软件,具有以下优势: 人工智能技术应用:藏汉翻译通利用了人工智能翻译和语音识别合成技术,提供智能藏文翻译服务。 高准确率:文字识别准确率可达90%,语音识别转化文字…

苍穹外卖--导入分类模块功能代码

把各层代码拷贝到所需文件夹下, 进行编译 在运行 提交和推送仓库

解锁AI大模型潜能:预训练、迁移学习与中间件编程的协同艺术

在人工智能的浩瀚星空中,大型预训练模型(Large Language Models, LLMs)犹如璀璨的星辰,引领着技术革新的浪潮。这些模型通过海量数据的滋养,学会了理解语言、生成文本乃至执行复杂任务的能力。然而,要让这些…

【正点原子i.MX93开发板试用连载体验】项目计划和开箱体验

本文最早发表于电子发烧友:【   】【正点原子i.MX93开发板试用连载体验】基于深度学习的语音本地控制 - 正点原子学习小组 - 电子技术论坛 - 广受欢迎的专业电子论坛! (elecfans.com)https://bbs.elecfans.com/jishu_2438354_1_1.html 有一段时间没有参加电子发…

Pyspider WebUI 未授权访问致远程代码执行漏洞复现

0x01 产品简介 Pyspider是由国人binux编写的强大的网络爬虫系统,它带有强大的WebUI(Web用户界面),为用户提供了可视化的编写、调试和管理爬虫的能力。这一特点使得Pyspider在爬虫框架中脱颖而出,尤其适合那些希望快速上手并高效开发爬虫的用户。允许用户直接在网页上编写…

Linux--线程的控制

目录 0.前言 1.pthread库 2.关于控制线程的接口 2.1.创建线程(pthread_create) 2.2.线程等待(pthread_join) 代码示例1: ​编辑 ***一些问题*** 2. 3.创建多线程 3.线程的终止 (pthread_exit /…

给数组/对象添加一个(key-value)对象

需要将一个value值前面加上key值,放进数组/对象中 this.$set(res.data[0],type,1) this.$set( target, key, value ) target:要更改的数据源(可以是对象或者数组) key:要更改的具体数据 value :重新赋的值。 结果:…

文华财经盘立方多空变色波段趋势线指标公式源码

文华财经盘立方多空变色波段趋势线指标公式源码&#xff1a; N1:20; N2:ROUND(N1/2,1); N3:ROUND(SQRT(N1),1); N4:2*EMA2(C,N2)-EMA2(C,N1); 尊重市场:EMA2(N4,N3),COLORRED,LINETHICK2; 尊重市场1:IF(尊重市场<REF(尊重市场,1), 尊重市场,NULL),COLORGREEN,LINETHIC…

C++之List模拟实现

目录 list的逻辑结构 构造函数 拷贝构造函数 赋值运算符重载 返回迭代器的初始位置 返回迭代器的最终位置 元素的插入 头插 尾插 删除元素 头删 尾删 清空整个链表 析构函数 正向迭代器 反向迭代器 整体代码 上期我们学写了list的基本操作&#xff0c;本期我…

苏东坡传-读书笔记十一

苏东坡对写作与风格所表示的意见最为清楚。他说做文章“大略如行云流水&#xff0c;初无定质&#xff0c;但常行于所当行&#xff0c;常止于所不可不止。文理自然&#xff0c;姿态横生。孔子曰&#xff1a;‘言之不文&#xff0c;行而不远。’又曰&#xff1a;‘辞达而已矣。’…

STC32G/F/8H通用无刷电机驱动板

STC32G/F/8H通用无刷电机驱动板 &#x1f4cc;相关篇《低成本STC32G8K64驱动控制BLDC开源入门学习方案》 ✨该驱动板是在上一版的基础上改版而来。这里的STC32G/F/8H所指的是封装型号为-LQFP48的STC32G8K64、STC32G12K128、STC32F12K54、STC8H8K64U。是一款兼容有感和无感设计的…

【Java算法】二分查找 下

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【算法工作坊】算法实战揭秘 一.山脉数组的峰顶索引 题目链接&#xff1a;852.山脉数组的峰顶 ​ 算法原理 这段代码实现了一个查找山峰数组中峰值索引的算法。山峰数组是一个先递增后递减的数组&…