哈喽大家好,我是咸鱼

好久不见甚是想念,2023 年最后一次法定节假日已经结束了,不知道各位小伙伴是不是跟咸鱼一样今天就开始“搬砖”了呢?

我们知道元组(tuple)是 Python 的内置数据类型,tuple 是一个不可变的值序列

tuple 的元素可以是任何类型,一般用在存储异构数据(例如数据库记录)的场景

那么今天这篇文章将带大家深入了解一下 tuple 以及它们的主要功能和示例(原文较长,我分成几个部分去讲)

原文链接:https://realpython.com/python-tuple/

前言

tuple 是不可变的,可以存储固定数量的元素(也可以叫项目,item)

例如可以通过 tuple 来表示笛卡尔坐标(x,y)、RGB 颜色(red,green,blue)或者数据库表中的记录(name,age,job)

tuple 的一些特点如下:

  • 有序:里面的元素可以按照顺序排列
  • 轻量级:与列表等其他序列相比,tuple 消耗的内存要少
  • 从零开始索引:可以从零开始索引访问里面的元素
  • 不可变:不可以改变里面的元素
  • 异构:可以存储不同数据类型的对象(包括可变对象)
  • 可嵌套:tuple 里面可以包含 tuple
  • 可迭代:能够遍历里面的元素
  • 可切片:可以从元组中提取一系列元素
  • 可组合:支持串联操作,可以使用串联运算符组合多个元组
  • 可哈希:里面的元素都是不可变时可以用作字典的键

在 python 中,tuple 是有序的,这意味着其元素保持原始插入顺序,这个顺序在 tuple 的生命周期内保持不变

>>> record = ("John", 35, "Python Developer")

>>> record
('John', 35, 'Python Developer')

可以按位置或索引访问元组中的元素(从零开始)

>>> record[0]
'John'
>>> record[1]
35
>>> record[2]
'Python Developer'

创建 tuple

tuple 是以逗号分隔的序列对象。要在元组中存储对象,需要一次创建包含其所有内容的元组对象

直接创建

# 语法
(item_0, item_1, ..., item_n)

需要注意的是,括号不是必需的,逗号才是。但是在大多数情况下括号可以提高代码的可读性

>>> jane = ("Jane Doe", 25, 1.75, "Canada")
>>> point = (2, 7)
>>> pen = (2, "Solid", True) >>> days = (
... "Monday",
... "Tuesday",
... "Wednesday",
... "Thursday",
... "Friday",
... "Saturday",
... "Sunday",
... )

尽管括号对于定义大多数 tuple 不是必需的,但在创建空 tuple 时必须包含它们:

>>> empty = ()
>>> empty
() >>> type(empty)
<class 'tuple'>

因为 tuple 是不可变的,所以创建空 tuple 之后无法往里面添加元素。到这里有小伙伴可能会问:既然这样为什么还要创建一个空 tuple?

例如现在有一个构建并返回 tuple 的函数,在一些情况下这个函数不会为生成的 tuple 创建元素,这样我们就需要返回一个空 tuple。以此来使得函数的返回值类型保持一致

除此之外,下面的情况也需要使用到括号

>>> "Hello, %s! You're %s years old." % ("Linda", 24)
'Hello, Linda! You're 24 years old.' >>> "Hello, %s! You're %s years old." % "Linda", 24
Traceback (most recent call last):
...
TypeError: not enough arguments for format string

当我们使用 % 进行格式化输出的时候:

  • 第一种加括号:使用括在括号中的元组作为 % 运算符的右侧操作数,按预期工作
  • 第二种没加括号:报错

我们创建单个元素的 tuple

>>> one_word = "Hello",
>>> one_word
('Hello',) >>> one_number = (42,)
>>> one_number
(42,)

可以看到括号不是必需的,尾随逗号才是

使用 tuple() 创建

还可以使用 tuple() 从可迭代对象(列表、集合、字典或字符串)中创建 tuple,默认生成一个空 tuple

# 语法
tuple([iterable])
>>> tuple(["Jane Doe", 25, 1.75, "Canada"])
('Jane Doe', 25, 1.75, 'Canada') >>> tuple("Pythonista")
('P', 'y', 't', 'h', 'o', 'n', 'i', 's', 't', 'a') >>> tuple({
... "manufacturer": "Boeing",
... "model": "747",
... "passengers": 416,
... }.values())
('Boeing', '747', 416) >>> tuple()
()

通过集合来创建 tuple 时需要注意集合是无序的,会影响生成 tuple 中的元素的最终顺序

如果我们从一个迭代器对象中创建一个tuple,那么 tuple() 函数会使用迭代器逐个生成元素,然后将这些元素组合成一个元组并返回

my_list = [1, 2, 3, 4, 5] # 可迭代对象
my_iterator = iter(my_list) # 转换为迭代器对象 my_iterator
my_tuple = tuple(my_iterator)
print(my_tuple) # 输出结果为:(1, 2, 3, 4, 5)

又或者从生成器表达式中创建 tuple,生成器是一种特殊的迭代器

>>> tuple(x**2 for x in range(10))
(0, 1, 4, 9, 16, 25, 36, 49, 64, 81)

tuple 索引和切片

tuple 中每一个元素都有一个整数索引,用于指定其在元组中的位置,索引从 0 开始

# 语法
tuple_object[index]
# 例子
>>> jane = ("Jane Doe", 25, 1.75, "Canada") >>> jane[0]
'Jane Doe'
>>> jane[1]
25
>>> jane[3]
'Canada'

用不同的索引为 tuple 建立索引,可以直接访问相关的值。如果使用大 O 符号表示时间复杂度,那么可以说索引是一个O(1)操作



这意味着 tuple 非常适合需要快速访问序列中的特定项的情况

len() 函数返回 tuple 长度

>>> len(jane)
4

如果使用大于或等于 tuple 长度的索引,则会报错

>>> jane[4]
Traceback (most recent call last):
...
IndexError: tuple index out of range

还可以使用负索引,负索引从右端开始数起

负索引对于所有 Python 序列(例如列表和字符串)都是通用的

>>> jane[-1]
'Canada' >>> jane[-2]
1.75



如果使用负索引,则 -len(tuple_object) 将成为元组中的第一项。如果使用低于此值的索引,则会报错

>>> jane[-5]
Traceback (most recent call last):
...
IndexError: tuple index out of range

对于嵌套 tuple,我们该如何访问到里面的元素?

>>> employee = (
... "John",
... 35,
... "Python Developer",
... ("Django", "Flask", "FastAPI", "CSS", "HTML"),
... )

答案是通过多层索引

>>> employee[-1][0]
'Django' >>> employee[-1][1]
'Flask'

tuple 切片

和其他序列一样,tuple 可以使用切片操作来提取其中的内容

# 语法
tuple_object[start:stop:step]

[start:stop:step] 此构造的一部分称为切片运算符。它由一对方括号和三个可选索引组成: startstopstep

其中第二个冒号不是必须的,如果 step为1的话就可以省略

Index Description Default Value
start 指定要开始切片的索引(开区间) 0
stop 指定希望切片停止提取元素的索引(闭区间) len(tuple_object)
step 提供一个整数值,表示切片在每个步骤中将跳过多少项 1
>>> days = (
... "Monday",
... "Tuesday",
... "Wednesday",
... "Thursday",
... "Friday",
... "Saturday",
... "Sunday",
... ) >>> days[:5]
('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday') >>> days[5:]
('Saturday', 'Sunday')

不可变特性

Python 的 tuple 是不可变的,这意味着一旦你创建了一个 tuple,你就不能就地更改或更新它的元素,只能创建新的 tuple 对象

>>> jane = ("Jane Doe", 25, 1.75, "Canada")

>>> jane[3] = "United States"
Traceback (most recent call last):
...
TypeError: 'tuple' object does not support item assignment

tuple 不可变的另一个含义是无法对其扩容缩容,与列表不同,元组没有.append().extend() .insert() .remove().clear() 方法

也不支持 del 语句

>>> point = (7, 14, 21)

>>> del point[2]
Traceback (most recent call last):
...
TypeError: 'tuple' object doesn't support item deletion

尽管 tuple 是不可变的,但是我们知道 tuple 里面可以存储任意类型的对象,包括可变对象

这意味着我们可以在 tuple 中存储列表、集合、字典等其他可变对象

>>> student_info = ("Linda", 18, ["Math", "Physics", "History"])

student_info 中前两个元素是不可变的,最后一个是列表(可变),所以我们可以对其进行更改

>>> student_info[2][2] = "Computer science"
>>> student_info
('Linda', 22, ['Math', 'Physics', 'Computer science'])

又因为 tuple 是不可变的(可哈希),所以可以用作字典中的 key

>>> student_courses = {
... ("John", "Doe"): ["Physics", "Chemistry"],
... ("Jane", "Doe"): ["English", "History"],
... } >>> student_courses[("Jane", "Doe")]
['English', 'History']

如果用作 key 的 tuple 里面包含可变元素,则会报错

>>> student_courses = {
... (["John", "Miguel"], "Doe"): ["Physics", "Chemistry"],
... (["Fatima", "Jane"], "Doe"): ["English", "History"],
... }
Traceback (most recent call last):
...
TypeError: unhashable type: 'list'

深挖 Python 元组 pt.1的更多相关文章

  1. 深挖Openstack Nova - Scheduler调度策略

    深挖Openstack Nova - Scheduler调度策略   一.  Scheduler的作用就是在创建实例(instance)时,为实例选择出合适的主机(host).这个过程分两步:过滤(F ...

  2. Python元组

    Python的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号. 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可. 如下实例: tup1 = ('physi ...

  3. Python 元组内置函数

    Python元组包含了以下内置函数 序号 方法及描述 1 cmp(tuple1, tuple2)比较两个元组元素. 2 len(tuple)计算元组元素个数. 3 max(tuple)返回元组中元素最 ...

  4. 深挖JDK动态代理(二):JDK动态生成后的字节码分析

    接上一篇文章深挖JDK动态代理(一)我们来分析一下JDK生成动态的代理类究竟是个什么东西 1. 将生成的代理类编程一个class文件,通过以下方法 public static void transCl ...

  5. 深挖JDK动态代理(一)

     最近在研究RPC框架,避免不了的就是在RPC调用中使用最多的则是动态代理的机制了,基于此,我们先来研究一下JDK动态代理 我们先来尝试着编写一下JDK动态代理的代码 1. 由于JDK动态代理是基于接 ...

  6. Python元组与字典详解

    Python 元组 Python的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号. 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可. 如下实例: tup ...

  7. Python 元组 count() 方法

    描述 Python 元组 count() 方法用于统计某个元素在元祖中出现的次数. 语法 count() 方法语法: T.count(obj) 参数 obj -- 元祖中统计的对象. 返回值 返回元素 ...

  8. Python 元组 index() 方法

    描述 Python 元组 index() 方法用于从元祖中找出某个对象第一个匹配项的索引位置,如果这个对象不在元祖中会报一个异常. 语法 index() 方法语法: T.index(obj[,star ...

  9. Python 元组 tuple() 方法

    描述 Python 元组 tuple() 方法用于将可迭代对象(字符串.列表.元祖.字典)转换为元组. 语法 tuple() 方法语法: tuple(iterable) 参数 iterable -- ...

  10. Python 元组 min() 方法

    描述 Python 元组 min() 方法返回元组中元素最小值. 语法 min() 方法语法: min(T) 参数 T -- 指定的元组. 返回值 返回元组中元素最小值. 实例 以下实例展示了 min ...

随机推荐

  1. 学习websocket,原来这么简单

    简单介绍 websocket WebSocket是一种在TCP连接上进行全双工通信的协议. WebSocket通信协议于2011年被IETF定为标准. 然后WebSocket API也被W3C定为标准 ...

  2. 深入浅出security学习笔记

    第一章 导入web和security依赖,然后默认提供了一个基于内存的UserDetailsServiceAutoConfiguration如下 会读取写入的user配置,SecurityProper ...

  3. Hugging News #0703: 在浏览器中运行 Whisper 模型、WAIC 分论坛活动邀请报名

    每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...

  4. Windows 环境下Docker 安装伪分布式 Hadoop

    1.环境 Windows 11 Docker 20.0.2 2.拉取镜像 我选择 ubuntu20.04: docker pull ubuntu:20.04 然后我们用命令看一下本地镜像: docke ...

  5. AutoreleasePool 的总结

    1.创建和释放时机问题 App启动后,苹果在主线程 RunLoop 里注册了两个 Observer,其回调都是 _wrapRunLoopWithAutoreleasePoolHandler(). 第一 ...

  6. 飞桨paddlespeech语音唤醒推理C定点实现

    前面的文章(飞桨paddlespeech语音唤醒推理C浮点实现)讲了飞桨paddlespeech语音唤醒推理的C浮点实现.但是嵌入式设备通常CPU频率低和memory小,在嵌入式设备上要想流畅的运行语 ...

  7. MyBatis(log4j)

    log4j介绍 Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件,甚至是套接口服务器.NT的事件记录器.UNIX Syslog守护 ...

  8. Ubuntu18.04 软件源更新:图形界面

    通过图形UI界面更新Ubuntu的软件源,手动修改虽然简单,但是要自己去找源,选一个系统配置好的更简单.但是新版的好像没有该功能,找到个奇葩的路径: 将Ubuntu16.04升级为Ubuntu18.0 ...

  9. 【hack】浅浅说说自己构造hack的一些逻辑~

    怎么说呢,相信很多考过竞赛的同学都会在平时的练习/考试中遭遇过100分但没有AC的情况,结果一看评测结果:subtask的数据点没过! 这时候就是遇到hack数据了,如果被这类数据卡住,说明你的代码可 ...

  10. Django2.2:UnicodeDecodeError: 'gbk' codec can't decode byte 0xa6 in position 9737: illegal multibyte sequence

    报错截图: 解决方案: 打开django/views下的debug.py文件,转到line331行: with Path(CURRENT_DIR, 'templates', 'technical_50 ...