上一节课为大家讲解了Python中的列表,它是一种容器型数据类型,我们可以通过定义列表类型的变量来保存和操作多个元素。当然,Python中容器型的数据类型肯定不止列表一种,接下来我们为大家讲解另一种重要的容器型数据类型,它的名字叫元组(tuple)。

定义和使用元组

在Python中,元组也是多个元素按照一定的顺序构成的序列。元组和列表的不同之处在于,元组是不可变类型,这就意味着元组类型的变量一旦定义,其中的元素不能再添加或删除,而且元素的值也不能进行修改。定义元组通常使用()字面量语法,元组类型支持的运算符跟列表是一样。下面的代码演示了元组的定义和运算。

# 定义一个三元组
t1 = (30, 10, 55)
# 定义一个四元组
t2 = ('骆昊', 40, True, '四川成都')
​
# 查看变量的类型
print(type(t1), type(t2))    # <class 'tuple'> <class 'tuple'>
# 查看元组中元素的数量
print(len(t1), len(t2))      # 3 4
​
# 通过索引运算获取元组中的元素
print(t1[0], t1[-3])         # 30 30
print(t2[3], t2[-1])         # 四川成都 四川成都
​
# 循环遍历元组中的元素
for member in t2:print(member)
​
# 成员运算
print(100 in t1)    # False
print(40 in t2)     # True
​
# 拼接
t3 = t1 + t2
print(t3)           # (30, 10, 55, '骆昊', 40, True, '四川成都')
​
# 切片
print(t3[::3])      # (30, '骆昊', '四川成都')# 比较运算
print(t1 == t3)    # False
print(t1 >= t3)    # False
print(t1 < (30, 11, 55))    # True

一个元组中如果有两个元素,我们就称之为二元组;一个元组中如果五个元素,我们就称之为五元组。需要提醒大家注意的是,()表示空元组,但是如果元组中只有一个元素,需要加上一个逗号,否则()就不是代表元组的字面量语法,而是改变运算优先级的圆括号,所以('hello', )和(100, )才是一元组,而('hello')和(100)只是字符串和整数。我们可以通过下面的代码来加以验证。

# 空元组
a = ()
print(type(a))    # <class 'tuple'>
# 不是元组
b = ('hello')
print(type(b))    # <class 'str'>
c = (100)
print(type(c))    # <class 'int'>
# 一元组
d = ('hello', )
print(type(d))    # <class 'tuple'>
e = (100, )
print(type(e))    # <class 'tuple'>

元组的应用场景

讲到这里,相信大家一定迫切的想知道元组有哪些应用场景,我们给大家举几个例子。

例子1:打包和解包操作。

当我们把多个用逗号分隔的值赋给一个变量时,多个值会打包成一个元组类型;当我们把一个元组赋值给多个变量时,元组会解包成多个值然后分别赋给对应的变量,如下面的代码所示。

# 打包
a = 1, 10, 100
print(type(a), a)    # <class 'tuple'> (1, 10, 100)
# 解包
i, j, k = a
print(i, j, k)       # 1 10 100

在解包时,如果解包出来的元素个数和变量个数不对应,会引发ValueError异常,错误信息为:too many values to unpack(解包的值太多)或not enough values to unpack(解包的值不足)。

a = 1, 10, 100, 1000
# i, j, k = a             # ValueError: too many values to unpack (expected 3)
# i, j, k, l, m, n = a    # ValueError: not enough values to unpack (expected 6, got 4)

有一种解决变量个数少于元素的个数方法,就是使用星号表达式,我们之前讲函数的可变参数时使用过星号表达式。有了星号表达式,我们就可以让一个变量接收多个值,代码如下所示。需要注意的是,用星号表达式修饰的变量会变成一个列表,列表中有0个或多个元素。还有在解包语法中,星号表达式只能出现一次。

a = 1, 10, 100, 1000
i, j, *k = a
print(i, j, k)          # 1 10 [100, 1000]
i, *j, k = a
print(i, j, k)          # 1 [10, 100] 1000
*i, j, k = a
print(i, j, k)          # [1, 10] 100 1000
*i, j = a
print(i, j)             # [1, 10, 100] 1000
i, *j = a
print(i, j)             # 1 [10, 100, 1000]
i, j, k, *l = a
print(i, j, k, l)       # 1 10 100 [1000]
i, j, k, l, *m = a
print(i, j, k, l, m)    # 1 10 100 1000 []

需要说明一点,解包语法对所有的序列都成立,这就意味着对字符串、列表以及我们之前讲到的range函数返回的范围序列都可以使用解包语法。大家可以尝试运行下面的代码,看看会出现怎样的结果。

a, b, *c = range(1, 10)
print(a, b, c)
a, b, c = [1, 10, 100]
print(a, b, c)
a, *b, c = 'hello'
print(a, b, c)

现在我们可以反过来思考一下函数的可变参数,可变参数其实就是将多个参数打包成了一个元组,可以通过下面的代码来证明这一点。

def add(*args):print(type(args), args)total = 0for val in args:total += valreturn total
​
​
add(1, 10, 20)        # <class 'tuple'> (1, 10, 20)
add(1, 2, 3, 4, 5)    # <class 'tuple'> (1, 2, 3, 4, 5)

例子2:交换两个变量的值。

交换两个变量的值是编程语言中的一个经典案例,在很多编程语言中,交换两个变量的值都需要借助一个中间变量才能做到,如果不用中间变量就需要使用比较晦涩的位运算来实现。在Python中,交换两个变量a和b的值只需要使用如下所示的代码。

a, b = b, a

同理,如果要将三个变量a、b、c的值互换,即b赋给a,c赋给b,a赋给c,也可以如法炮制。

a, b, c = b, c, a

需要说明的是,上面并没有用到打包和解包语法,Python的字节码指令中有ROT_TWO和ROT_THREE这样的指令可以实现这个操作,效率是非常高的。但是如果有多于三个变量的值要依次互换,这个时候没有直接可用的字节码指令,执行的原理就是我们上面讲解的打包和解包操作。

例子3:让函数返回多个值。

有的时候一个函数执行完成后可能需要返回多个值,这个时候元组类型应该是比较方便的选择。例如,编写一个找出列表中最大值和最小的函数。

def find_max_and_min(items):"""找出列表中最大和最小的元素:param items: 列表:return: 最大和最小元素构成的二元组"""max_one, min_one = items[0], items[0]for item in items:if item > max_one:max_one = itemelif item < min_one:min_one = itemreturn max_one, min_one

上面函数的return语句中有两个值,这两个值会组装成一个二元组然后返回。所以调用find_max_and_min函数会得到这个二元组,如果愿意也可以通过解包语法将二元组中的两个值分别赋给两个变量。

元组和列表的比较

这里还有一个非常值得探讨的问题,Python中已经有了列表类型,为什么还需要元组这样的类型呢?这个问题对于初学者来说似乎有点困难,不过没有关系,我们先抛出观点,大家可以一边学习一边慢慢体会。

  • 元组是不可变类型,不可变类型更适合多线程环境,因为它降低了并发访问变量的同步化开销。关于这一点,我们会在后面讲解多线程的时候为大家详细论述。
  • 元组是不可变类型,通常不可变类型在创建时间和占用空间上面都优于对应的可变类型。我们可以使用sys模块的getsizeof函数来检查保存相同元素的元组和列表各自占用了多少内存空间。我们也可以使用timeit模块的timeit函数来看看创建保存相同元素的元组和列表各自花费的时间,代码如下所示。
import sys
import timeit
​
a = list(range(100000))
b = tuple(range(100000))
print(sys.getsizeof(a), sys.getsizeof(b))    # 900120 800056
​
print(timeit.timeit('[1, 2, 3, 4, 5, 6, 7, 8, 9]'))
print(timeit.timeit('(1, 2, 3, 4, 5, 6, 7, 8, 9)'))
  • Python中的元组和列表是可以相互转换的,我们可以通过下面的代码来做到。
# 将元组转换成列表
info = ('骆昊', 175, True, '四川成都')
print(list(info))       # ['骆昊', 175, True, '四川成都']
# 将列表转换成元组
fruits = ['apple', 'banana', 'orange']
print(tuple(fruits))    # ('apple', 'banana', 'orange')

简单的总结

列表和元组都是容器型的数据类型,即一个变量可以保存多个数据。列表是可变数据类型元组是不可变数据类型,所以列表添加元素、删除元素、清空、排序等方法对于元组来说是不成立的。但是列表和元组都可以进行拼接成员运算索引和切片这些操作,就如同之前讲到的字符串类型一样,因为字符串就是字符按一定顺序构成的序列,在这一点上三者并没有什么区别。我们推荐大家使用列表的生成式语法来创建列表,它很好用,也是Python中非常有特色的语法。

从零开始学Python:第十二课-常用数据结构之元组相关推荐

  1. 零基础入门学Python(十二)—— 魔法方法(下)

    零基础入门学Python系列内容的学习目录→\rightarrow→零基础入门学Python系列内容汇总. 魔法方法(下) 1. 构造和析构 2. 算术运算 3. 简单定制 4. 属性访问 5. 描述 ...

  2. 零基础入门学Python(十二)—— 魔法方法(上)

    零基础入门学Python系列内容的学习目录→\rightarrow→零基础入门学Python系列内容汇总. 魔法方法(上) 1. 构造和析构 1.1 _ _ init _ _(self[, ...]) ...

  3. 【云原生 | 从零开始学Kubernetes】十二、k8spod的生命周期与容器钩子

    该篇文章已经被专栏<从零开始学k8s>收录 上一篇文章:k8s污点.容忍度和pod状态 点击跳转 pod生命周期 Init 容器 主容器 容器钩子 创建 pod 需要经过哪些阶段? Pod ...

  4. 十二、Python第十二课——函数

    (请先看置顶博文)https://blog.csdn.net/GenuineMonster/article/details/104495419 目录 (请先看置顶博文)https://blog.csd ...

  5. java 根据经纬度计算多边形的面积_强基初中数学amp;学Python——第二十九课 根据海伦秦九韶公式编程计算三角形面积...

    问题:如果把边长都是有理数的三角形称作"有理三角形",编程计算"有理三角形"的面积(有理数或带根号的无理数,不是浮点数). 关键点分析:根号中的底化成最简分数, ...

  6. 少儿编程100讲轻松学python(十二)-python如何将数据写入txt

    前言 python将数据写入txt文本文件: 首先打开txt文件: 然后向文件写入数据,代码为[file_handle.write('helloword你好 '):file_handle.writel ...

  7. 看漫画学Python 第十二章代码

    12.1 打开文件 #open(file,mode = 'r',encoding = None,errors = None) f = open('test.txt','w+') #以w+模式打开文件, ...

  8. 从零开始学Pytorch(十二)之凸优化

    尽管优化方法可以最小化深度学习中的损失函数值,但本质上优化方法达到的目标与深度学习的目标并不相同. 优化方法目标:训练集损失函数值 深度学习目标:测试集损失函数值(泛化性) %matplotlib i ...

  9. 学习《Linux就该这么学》第十二课

最新文章

  1. ​20210716未来智能实验室收录资料
  2. phpstrom xdebug配置
  3. MATLAB 图像的傅里叶变换
  4. [zz]mysql 和 mongo db 语法对比
  5. python正则表达式group用法_【Python】正则表达式用法
  6. java内部类外部类_Java内部类:如何在内部类中返回外部类对象
  7. 023文件类型,权限,chmod,文件特殊属性
  8. IE6,IE7下按钮(BUTTON)变宽
  9. Delphi XE2 之 FireMonkey 入门(41) - 控件基础: TListBox
  10. 【MySQL高性能】Canal数据同步神器
  11. 电子科技大学 计算机学院 夏令营,2018年电子科技大学全校各学院保研夏令营通知信息大汇总...
  12. minimax算法和Alpha-Beta pruning实现英式跳棋
  13. Java后端开发工作 - 写接口
  14. Layui文件下载(VIP典藏版)
  15. mysql语句总结_mysql语句总结
  16. 被房地产坑惨的老板电器,终于要“回血”了!
  17. JavaWeb (SSM框架)
  18. 微金所张继业:规范化运作 回馈投资人
  19. 详述numpy中的np.random.rand()、np.random.randn()、np.random.randint()、np.random.uniform()函数的用法
  20. 2022新赛点:传统车企要向新势力的舒适圈开炮?

热门文章

  1. 图 邻接矩阵的深度优先遍历
  2. 谷歌浏览器超实用快捷键
  3. 《Learning from Synthetic Data for Crowd Counting in the Wild》阅读与调试
  4. CMD命令运行java程序
  5. 图片另存为找不到桌面
  6. vim在同一个窗口中同时编辑多个文件以及自动格式化代码
  7. BFS【古希腊之争(二)】(bfs+优先队列)
  8. vue的父子组件通信
  9. 【神界原罪2】被困的精灵(The Imprisoned Elf)[支线]桔子洛斯对话第三项可以得到桔子
  10. python文件读写格式