16、Python之容器:元组与列表、推导式与生成式,差之毫厘谬以千里
引言
从上一篇文章开始了对Python中容器的介绍,已经对列表的简单使用做了一些介绍,今天这篇文章,打算首先简单介绍一下元组,同时比较一下元组、列表的异同,然后就列表、元组的一些比较实用的用法,做一些补充说明。
本文的主要内容大概如下:
1、Python中元组的简单介绍
2、元组就是不可变列表?
3、关于遍历的其他方式
4、推导式与生成式的比较
Python中的tuple(元组)
在Python中提供了tuple的容器类型,可以实现不可变容器的支持。
tuple的特点主要有:
1、不可变性:元组一旦创建,不能修改、添加、删除其中的元素(需要注意不可变的严格程度)。
2、有序性:如同列表,元组也是有序的,可以通过索引访问。
3、允许重复:元组不同于set(),元素是可以重复的。
4、支持多种类型:如同列表一样,可以放入任何类型的元素。
元组的使用,除了不能增、删、改,基本是跟列表相同的。
但是,需要注意的是,不可变性的程度,是开发者需要注意到的。
zhangsan = ('张三', 18, '男', ['reading', 'basketball'])
print(zhangsan)
# 报错
zhangsan[1] = 23
执行结果:
如果改的是嵌套容器的元素呢:
zhangsan = ('张三', 18, '男', ['reading', 'basketball'])
print(zhangsan)
# 报错
# zhangsan[1] = 23
# 改变元素的内容
zhangsan[3].append('running')
print(zhangsan)
执行结果:
所以,这个元组不可变的说法,需要开发者自己要有所思考、感知的。
tuple就是不可变的列表?
有些入门教材中,总是习惯于把元组称之为“不可变列表”,刚开始简单使用,其实也是无关紧要的。但是,如果要真正理解元组,这样的模糊认知其实是不够的。
首先,从语意上来说,元组,适合于用作一条记录的存储,而列表更适合一组记录的存储。所以,元组中的项数与项的顺序也有具有了语意,自然不能随意更改。
# 存储了一条记录,项依次为姓名、年龄、性别、爱好,顺序自然不能随意变更,每条记录分别以元组存储表达,多条记录则将之放入列表
zhangsan = ('张三', 18, '男', ['reading', 'basketball'])
lisi = ('李四', 23, '女', ['reading', 'singing'])
persons = [zhangsan, lisi]
print(persons)
执行结果:
其次,元组是否一定能作为字典的key,这也是需要打个问号的。能作为字典key的,一定是可以哈希的。元组一定可以哈希吗?可以使用内置函数hash()来判断:
zhangsan = ('张三', 18, '男', ['reading', 'basketball'])
# 本行会抛出TypeError的异常
hash(zhangsan)
执行结果:
因为元组中存储了不可哈希的元素。
那么,自然也不能作为字典的key:
zhangsan = ('张三', 18, '男', ['reading', 'basketball'])
d1 = {zhangsan: 10}
执行结果:
最后,除了可以作为不可变列表使用之外,tuple相较于list还是有性能上的优势的:
1、在字面量的构建上,元组可以一次生成,并作为常量存储。列表需要逐个入栈,然后构建列表。
2、给定一个元组zs,tuple(ts)直接返回t的引用,不涉及复制。相比之下,列表ls,list(ls)则会创建zs的副本。
zs = ('张三', 18, '男', ['reading', 'basketball'])
zs2 = tuple(zs)
print(id(zs))
print(id(zs2))ls = ['李四', 23, '女', ['reading', 'singing']]
ls2 = list(ls)
print(id(ls))
print(id(ls2))
执行结果:
3、在内存分配和引用存储上,元组长度固定,所以分配的内存空间刚好够用;而列表需要考虑追加元素,所以实际的内存空间会多分配一些。元组中元素的引用都存储在元组结构体中的一个数组中,而列表则把元素的引用数组存储在别处。主要是因为列表可以变长,一旦超出当前分配的空间,Python就需要重新分配引用数组来腾出空间。
关于遍历的其他方式
关于对列表和元组的遍历,其实有两个比较好用的“函数”:enumerate()和zip(),其实,不应该说是函数,严谨来说应该是类:
通过使用enumerate,可以生成带指定索引的元组格式的元素:
from faker import Faker
fk = Faker('zh_CN')names = [fk.unique.name() for _ in range(5)]
print(names)
print('='*5 + 'for names' + '='*5)
# 需要按照编号从1开始输出
# 使用for直接遍历:
for i in range(len(names)):print(f"{i + 1}: {names[i]}")
print('='*5 + 'for enumerate' + '='*5)
# 使用enumerate进行遍历:
for idx, name in enumerate(names, start=1):print(f"{idx}: {name}")
执行结果:
通过使用zip,可以将两个列表进行拉链,一一组合为元组的形式。
比如,现在有两个列表,分别存放姓名和性别,需要将每个人的姓名、性别同时输出:
names = [fk.unique.name() for _ in range(5)]
genders = [fk.passport_gender() for _ in range(5)]
print('='*5 + 'for names' + '='*5)
# 使用for直接遍历:
for i in range(len(names)):print(f"{names[i]}: {genders[i]}")
print('='*5 + 'for zip' + '='*5)
# 使用zip进行遍历:
for name, gender in zip(names, genders):print(f"{name}: {gender}")
执行结果:
如果两个列表的长度不同呢,我们只取出能匹配上的,匹配不上的就丢弃了,使用zip,自动就可以做到了,但是普通的循环,需要我们自己处理了:
names = [fk.unique.name() for _ in range(5)]
# 性别列表比姓名多了一个
genders = [fk.passport_gender() for _ in range(6)]
print('='*5 + 'for names' + '='*5)
# 使用for直接遍历:
# 长度不同时,需要按照最短的那个来
for i in range(min(len(names), len(genders))):print(f"{names[i]}: {genders[i]}")
print('='*5 + 'for zip' + '='*5)
# 使用zip进行遍历:
for name, gender in zip(names, genders):print(f"{name}: {gender}")
此外,zip结合前面提过的*号,还可以实现unzip的效果:
from faker import Faker
fk = Faker('zh_CN')name_gender_map = [(fk.unique.name(), fk.passport_gender()) for _ in range(5)]
print(name_gender_map)
names, genders = zip(*name_gender_map)
print(names)
print(genders)
执行结果:
列表推导式与生成器表达式
前面文章中,已经简单介绍了列表推导式的使用,本文将介绍一种新的列表构建的方式——生成器表达式。
使用列表推导式和生成器表达式都可以快速构建一个列表对象(序列),代码编写很快,实际代码执行也会很快,甚至这种一行代码替代for循环的代码习惯之后,更加易于理解!
相较于列表推导式,生成器表达式占用的内存更少,因为生成器表达式使用迭代器协议逐个产生元素,而不是构建整个列表提供给其他构造函数。
生成器表达式的语法跟列表推导式几乎一样,只是把方括号[]换成了圆括号()。
from faker import Faker
fk = Faker('zh_CN')persons = [(fk.name(), fk.random_int(10, 150), fk.random_int(140, 200)) for _ in range(10)]
persons_new = ((fk.name(), fk.random_int(10, 150), fk.random_int(140, 200)) for _ in range(10))
print(type(persons))
print(type(persons_new))
for p in persons_new:print(p)
此外,在实际代码编写时,需要注意的是:
Python会忽略[]、{}和()内部的换行。因此,列表、列表推导式、元组、字典等结构完全可以分成几行来写,无须使用续行转义符\。
总结
本文简单介绍了Python中元组的特点,同时对比了元组与列表、推导式与生成式。这些粗略看来,相差不大的概念,仔细思考之后,还是能发现很多值得注意的点,而这些可能就决定了Python代码编写的质量,以及实际运行的效率。
相关文章:

16、Python之容器:元组与列表、推导式与生成式,差之毫厘谬以千里
引言 从上一篇文章开始了对Python中容器的介绍,已经对列表的简单使用做了一些介绍,今天这篇文章,打算首先简单介绍一下元组,同时比较一下元组、列表的异同,然后就列表、元组的一些比较实用的用法,做一些补…...
HTTP协议——请求头和请求体详情
HTTP协议-请求头和请求体 请求头 请求头(Request Header)是在HTTP协议中用于描述一个HTTP请求的元数据。它是客户端发送给服务器的一部分请求信息,包含了客户端的相关配置和要求。 请求头通常包含以下几个部分: 1. 请求方法(Req…...
编程中的智慧之设计模式二
设计模式:深度解析与实战应用 在上一篇文章中,我们探讨了创建型模式、结构型模式和行为模式中的一些常用模式及其Java实现。本篇将继续深入探讨设计模式,重点介绍更多的行为模式以及架构模式在实际开发中的应用。 行为模式 责任链模式&…...

基于python的百度资讯爬虫的设计与实现
研究背景 随着互联网和信息技术的飞速发展,网络已经成为人们获取信息的主要来源之一。特别是搜索引擎,作为信息检索的核心工具,极大地改变了人们获取信息的方式。其中,百度作为中国最受欢迎的搜索引擎之一,其新闻搜索…...

用 WireShark 抓住 TCP
Wireshark 是帮助我们分析网络请求的利器,建议每个同学都装一个。我们先用 Wireshark 抓取一个完整的连接建立、发送数据、断开连接的过程。 简单的介绍一下操作流程。 1、首先打开 Wireshark,在欢迎界面会列出当前机器上的所有网口、虚机网口等可以抓取…...

Lua基础知识入门
1 基础知识 标识符:标识符的定义和 C语言相同:字母和下划线_ 开头, 下划线_ 大写字母一般是lua保留字, 如_VERSION 全局变量:默认情况下,变量总是认为是全局的,不需要申明,给一个变…...

【机器学习实战】Datawhale夏令营2:深度学习回顾
#DataWhale夏令营 #ai夏令营 文章目录 1. 深度学习的定义1.1 深度学习&图神经网络1.2 机器学习和深度学习的关系 2. 深度学习的训练流程2.1 数学基础2.1.1 梯度下降法基本原理数学表达步骤学习率 α梯度下降的变体 2.1.2 神经网络与矩阵网络结构表示前向传播激活函数…...
开发扫地机器人系统时无法兼容手机解决方案
在开发扫地机器人系统时,遇到无法兼容手机的问题,可以从以下几个方面寻求解决方案: 一、了解兼容性问题根源 ① 操作系统差异:不同手机可能运行不同的操作系统(如iOS、Android),且即使是同一操…...
Elasticsearch 角色和权限管理
在大数据和云计算日益普及的今天,Elasticsearch 作为一款强大的开源搜索引擎和数据分析引擎,被广泛应用于日志分析、全文搜索、实时监控等领域。随着业务规模的扩大和数据敏感性的增加,对 Elasticsearch 的访问控制和权限管理也变得越来越重要…...

华为HCIP Datacom H12-821 卷42
42.填空题 如图所示,MSTP网络中SW1为总根,请将以下交换机与IST域根和主桥配对。 参考答案:主桥1468 既是IST域根又是主桥468 既不是又不是就是25 解析: 主桥1468 既是IST域根又是主桥468 既不是又不是就是25 43.填空题 网络有…...

【精品资料】物业行业BI大数据解决方案(43页PPT)
引言:物业行业BI(Business Intelligence,商业智能)大数据解决方案是专为物业管理公司设计的一套综合性数据分析与决策支持系统。该解决方案旨在通过集成、处理、分析及可视化海量数据,帮助物业企业提升运营效率、优化资…...

推荐一款处理TCP数据的架构--EasyTcp4Net
EasyTcp4Net是一个基于c# Pipe,ReadonlySequence的高性能Tcp通信库,旨在提供稳定,高效,可靠的tcp通讯服务。 基础的消息通讯 重试机制 超时机制 SSL加密通信支持 KeepAlive 流量背压控制 粘包和断包处理 (支持固定头处理,固定长度处理,固定字符处理) 日志支持Pipe &…...
2、电脑各部件品牌介绍 - 计算机硬件品牌系列文章
笔者是一个电脑IT达人,对于电脑硬件挺感兴趣,今天有必要讲讲关于电脑各部件的品牌问题。关于电脑硬件介绍,见博文版块:计算机硬件系列 。下面对电脑的各部件品牌等进行介绍,便于大家选购电脑的时候做参考。 1、 CPU&am…...
Git【撤销远程提交记录】
在实际开发中,你是否遇到过错误的提交了代码,想要删掉本次提交记录的情况,你可以按照如下方法实现。 1、使用 git revert 如果你想要保留历史记录,并且对远程仓库其他使用者的影响最小,你可以使用 git revert 命令。这…...
java基础学习:序列化之 - Fast serialization
在Java中,序列化是将对象的状态转换为字节流的过程,以便保存到文件、数据库或通过网络传输。Java标准库提供了java.io.Serializable接口和相应的机制来进行序列化和反序列化。然而,标准的Java序列化机制性能较低,并且生成的字节流…...
Microsoft Build 2024 推出 .NET 9:Tensor<T>、 OpenAI Collaboration和.NET Aspire
在 Microsoft Build 2024 上,.NET 9 4 发布,引入了用于深度学习的 Tensor 类型以及与 OpenAI Collaboration实现GPT4o和Assistants v2等功能。这些最新改进还带来了 .NET Aspire,简化了云原生应用开发。更新涵盖 ASP.NET Core、Blazor 和 .NE…...

【Neural signal processing and analysis zero to hero】- 2
Nonstationarities and effects of the FT course from youtube: 传送地址 why we need extinguish stationary and non-stationary signal, because most of neural signal is non-stationary. Welch’s method for smooth spectral decomposition Full FFT method y…...

好用的AI搜索引擎
1. 360AI 搜索 访问 360AI 搜索: https://www.huntagi.com/sites/1706642948656.html 360AI 搜索介绍: 360AI 搜索,新一代智能答案引擎,值得信赖的智能搜索伙伴,为复杂搜索提供专业支持,解锁更相关、更全面的答案。AI…...

十、Java集合 ★ ✔(模块18-20)【泛型、通配符、List、Set、TreeSet、自然排序和比较器排序、Collections、可变参数、Map】
day05 泛型,数据结构,List,Set 今日目标 泛型使用 数据结构 List Set 1 泛型 1.1 泛型的介绍 ★ 泛型是一种类型参数,专门用来保存类型用的 最早接触泛型是在ArrayList,这个E就是所谓的泛型了。使用ArrayList时,只要给E指定某一个类型…...

阿里云开源 Qwen2-Audio 音频聊天和预训练大型音频语言模型
Qwen2-Audio由阿里巴巴集团Qwen团队开发,它能够接受各种音频信号输入,对语音指令进行音频分析或直接文本回复。与以往复杂的层次标签不同,Qwen2-Audio通过使用自然语言提示简化了预训练过程,并扩大了数据量。 喜好儿网 Qwen2-Au…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...