哈喽大家好,我是咸鱼

在《深挖 Python 元组 pt.1》中我们了解 Python 元组的一些概念(索引和切片等),以及如何创建元组,最重要的是我们还介绍了元组的不可变特性

那么今天我们来继续深挖 Python 元组

打包&解包

在 python 中,元组可以被打包(packing )和解包(unpacking

例如,point = x, y, z 将会把 x, y 和 z 的值打包到 point 中,于是创建了一个新元组

>>> x = 1
>>> y = 2
>>> z = 3
>>> point = x,y,z
>>> point
(1, 2, 3)

我们还可以执行反向操作(解包),将元组 point 的值解包为适当数量的变量

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

>>> x, y, z = point
>>> x
7
>>> y
14
>>> z
21

可以看到,x, y, z = point 神奇地将point的内容解压缩为三个变量。注意,值按顺序转到变量。(第一个值归第一个变量,第二个值归第二个变量,依此类推)

Python 3.5 扩展了元组解包语法,以处理各种可迭代对象

所以不单单元组可以解包,可迭代对象也可以解包

在常规解包中,变量的数量必须与要解包的值的数量相匹配。否则会报错

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

>>> x, y = point
Traceback (most recent call last):
...
ValueError: too many values to unpack (expected 2)

解包最常见的用例就是利用解包在变量之间交换值

没有解包的话使用常规赋值在两个变量之间交换值,必须使用临时变量

>>> a = 200
>>> b = 400 >>> temp = a
>>> a = b
>>> b = temp >>> a
400
>>> b
200

通过解包来交换变量值

>>> a = 200
>>> b = 400 >>> a, b = b, a >>> a
400
>>> b
200

解包还有一个用处是并行分配,比如说下面的操作:我们在进行赋值时需要知道对应的索引

>>> employee = ("John Doe", 35, "Python Developer")

>>> name = employee[0]
>>> age = employee[1]
>>> job = employee[2]

如果通过解包来实现,则无需使用索引。这样能使代码更易阅读和理解,且不易出错

>>> name, age, job = ("John Doe", 35, "Python Developer")

Python 还有一个打包和解包运算符 ( *,我们可以使用它让解包(打包)操作更加灵活

例如当左边的变量数和右边元组的元素数量不匹配时,可以使用 * 使得单个变量接收多个值

>>> numbers = (1, 2, 3, 4, 5)

>>> *head, last = numbers
>>> head
[1, 2, 3, 4]
>>> last
5 >>> first, *middle, last = numbers
>>> first
1
>>> middle
[2, 3, 4]
>>> last
5 >>> first, second, *tail = numbers
>>> first
1
>>> second
2
>>> tail
[3, 4, 5] >>> first, *_ = numbers
>>> first
1

关于这个操作符的更多用法,可以看我之前的文章:python 星号 * 还能这么用》

函数返回元组

在某些情况下,需要从函数返回多个值。所以可以构建一个带有逗号分隔的一系列参数的 return 语句,这样返回的是一个元组

我们还可以使函数返回值是列表,这样需要我们显式地使用方括号来构建列表

内置 divmod() 函数是返回多个值的函数的一个很好的例子。该函数接受两个数字,并在执行整数除法时返回一个包含商和余数的元组:

>>> divmod(4, 2)
(2, 0) # 由于该函数返回元组,因此可以使用解包语法将每个值存储在其专用变量中
>>> quotient, remainder = divmod(8, 2)
>>> quotient
4
>>> remainder
0

又或者我打算写一个函数,这个函数返回一组数的最大值和最小值

>>> def find_extremes(iterable):
... data = tuple(iterable)
... if len(data) == 0:
... raise ValueError("input iterable must not be empty")
... return min(data), max(data)
... >>> extremes = find_extremes([3, 4, 2, 6, 7, 1, 9])
>>> extremes
(1, 9) >>> type(extremes)
<class 'tuple'>

可以看到函数的返回值有两个:最大值、最小值。当用逗号分隔一系列值时,将创建一个元组。因此,此函数返回一个 tuple 对象

深拷贝浅拷贝

当需要转换数据时,通常需要复制对象,同时保持原始数据不变。在处理可变数据类型(如列表和字典)时,副本非常有用

副本可以在不影响原数据的情况下对数据进行更改

  • 直接赋值

我们先来看一个例子

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

>>> student_profile = student_info[:]
>>> id(student_info) == id(student_profile)
True
>>> id(student_info[0]) == id(student_profile[0])
True
>>> id(student_info[1]) == id(student_profile[1])
True
>>> id(student_info[2]) == id(student_profile[2])
True

可以看到,student_info、 student_profile 是对同一元组对象的引用。所以, student_profile 是 的 student_info 别名而不是副本

  • 浅拷贝

copy 模块中的 copy() 函数生成等效结果

>>> from copy import copy

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

>>> student_profile = copy(student_info)
>>> id(student_info) == id(student_profile)
True
>>> id(student_info[0]) == id(student_profile[0])
True
>>> id(student_info[1]) == id(student_profile[1])
True
>>> id(student_info[2]) == id(student_profile[2])
True

可以看到,两个变量student_info、 student_profile 都包含对同一元组对象和相同元素的引用

上面的元组里面包含了一个列表元素,我们知道列表是可变的,我们来试着更改一下

>>> student_profile[2][2] = "Computer science"

>>> student_profile
('Linda', 18, ['Math', 'Physics', 'Computer science'])
>>> student_info
('Linda', 18, ['Math', 'Physics', 'Computer science'])

可以看到,student_profile 更改会影响 student_info 中的原始数据

  • 深拷贝

下面的例子中, student_info 通过 deepcopy() 函数制作了student_profile

>>> from copy import deepcopy

>>> student_info = ("Linda", 18, ["Math", "Physics", "History"])
>>> student_profile = deepcopy(student_info) >>> id(student_info) == id(student_profile)
False
>>> id(student_info[0]) == id(student_profile[0])
True
>>> id(student_info[1]) == id(student_profile[1])
True
>>> id(student_info[2]) == id(student_profile[2])
False

可以看到,两个变量student_info、 student_profile 指向的元组对象不是同一个

如果我们对里面的列表元素进行更改

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

可以看到,对student_profile 的修改不会影响 student_info 中的数据

总结一下:

  • 元组的浅拷贝不会创建一个新的对象(副本)。
  • 元组的深拷贝创建一个新的元组对象
    • 对于元组内的不可变元素,它们仍然会共享相同的内存地址
    • 对于元组内的可变元素,则是创建了一个新的对象,不共享内存地址

其他操作

  • 元组拼接和重复

在 Python 中连接两个元组,可以使用加号运算符 ( +

>>> personal_info = ("John", 35)
>>> professional_info = ("Computer science", ("Python", "Django", "Flask")) >>> profile = personal_info + professional_info
>>> profile
('John', 35, 'Computer science', ('Python', 'Django', 'Flask'))

需要注意的是,+ 左右两边必须都是元组,即只能将元组跟元组拼接。如果元组跟列表或其他对象拼接的话,会报错

>>> (0, 1, 2, 3, 4, 5) + [6, 7, 8, 9]
Traceback (most recent call last):
...
TypeError: can only concatenate tuple (not "list") to tuple

元组使用重复运算符 ( * )将元素克隆多次

>>> numbers = (1, 2, 3)

>>> numbers * 3
(1, 2, 3, 1, 2, 3, 1, 2, 3) >>> 4 * numbers
(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)
  • 元组反转和排序

内置 reversed() 函数将序列作为参数,并返回一个迭代器,该迭代器以相反的顺序从输入序列生成值

>>> days = (
... "Monday",
... "Tuesday",
... "Wednesday",
... "Thursday",
... "Friday",
... "Saturday",
... "Sunday",
... ) >>> reversed(days)
<reversed object at 0x107032b90> >>> tuple(reversed(days))
(
'Sunday',
'Saturday',
'Friday',
'Thursday',
'Wednesday',
'Tuesday',
'Monday'
)

使用元组作为参数进行调用 reversed() 时,将获得一个迭代器对象,该对象以相反的顺序生成项

如果要对元组进行排序,可以使用内置 sorted() 函数,该函数将值的可迭代对象作为参数并以列表形式返回排序后的值

>>> numbers = (2, 9, 5, 1, 6)

>>> sorted(numbers)
[1, 2, 5, 6, 9]

如果元组里面的元素数据类型不一致(异构数据),则无法排序

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

  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. 数据库系列:RR和RC下,快照读的区别

    数据库系列:MySQL慢查询分析和性能优化 数据库系列:MySQL索引优化总结(综合版) 数据库系列:高并发下的数据字段变更 数据库系列:覆盖索引和规避回表 数据库系列:数据库高可用及无损扩容 数据库 ...

  2. 泛微OA与ERP集成的关键要点

    泛微OA办公系统与ERP系统的集成是为了实现企业内部各个系统之间的数据共享和协同工作,提高工作效率和管理水平.下面将详细介绍泛微OA办公系统如何与ERP系统集成以及轻易云数据集成平台在该过程中发挥的重 ...

  3. SFX的妙用——如何在不安装软件的情况下打开自定义格式文件?

    前段时间看到群友讨论压缩包能不能运行,想起了N年前用自解压文件SFX实现的一个"需求":在没有安装任何应用软件的Windows(当时还要支持XP)上能双击打开自定义格式的文件.当时 ...

  4. STM32外设:最小系统、低功耗模式

    最小系统 启动引脚 BOOT0.BOOT1:用于设置系统的启动方式 下载引脚 JTAG的IO:JTMS.JTCK.JTDI.JTDO.NJTRST SW的IO:SWDIO.SWCLK 硬件设计 NUC ...

  5. C#中await /async 的使用场景,优点,使用方法介绍

    async/await 是 C# 中异步编程的关键特性,它使得异步代码编写更为简单和直观.下面深入详细描述了 async/await 的使用场景.优点以及一些高级使用方法,并提供了相应的实例源代码. ...

  6. Linux笔记03: Linux常用命令_3.1命令的基本格式

    3.1命令的基本格式 3.1.1 命令提示符 [root@localhost ~]# 这就是Linux系统的命令提示符.各部分含义如下: ●[]:这是提示符的分隔符号,没有特殊含义. ●root:显示 ...

  7. idea常用快捷键使用

    idea常用快捷键使用:1.shift+u 大小写2.alt+shift+u 驼峰命名(插件:CamelCase)3.ctrl+alt 点击跳转实现类4.ctrl 点击跳转接口类5.Alt+F7 查看 ...

  8. 我用 AI 写的《JavaScript 工程师的 Python 指南》电子书发布啦!

    关于本书 你好,我是 luckrnx09,一名靠 React 恰饭的前端工程师,很高兴向你介绍我的第一本开源电子书<JavaScript 工程师的 Python 指南>. 本书的内容完全免 ...

  9. [NOI online2022普及C]字符串

    题目描述 Kri 非常喜欢字符串,所以他准备找 \(t\) 组字符串研究. 第 \(i\) 次研究中,Kri 准备了两个字符串 \(S\) 和\(R\) ,其中 \(S\) 长度为 \(n\),且只由 ...

  10. ubuntu 22.04搭建本地源

    ubuntu 22.04搭建本地源 基于服务器无法联网的情况下,从一台可以上网的服务器下载软件包和依赖,再在无法联网的服务器中搭建本地源,安装环境. 下载(包括依赖): cd /root mkdir ...