Python从0到100(八):Python元组介绍及运用

一、什么是元组

Python的元组与列表类似,不同之处在于元组的元素不能修改元组使用小括号,列表使用方括号

python 复制代码
tup1 = ('physics', 'chemistry', 1997, 2000)
tup2 = (1, 2, 3, 4, 5 )
tup3 = "a", "b", "c", "d"

二、定义和使用元组

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

python 复制代码
# 空元组
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. 访问元组

元组可以使用下标索引来访问元组中的值

python 复制代码
tuple=('hello',100,4.5)
print(tuple[0])
print(tuple[1])
print(tuple[2])

2. 元组不允许修改元组

python 复制代码
tup1 = (12, 34.56);
tup2 = ('abc', 'xyz')
# 以下修改元组元素操作是非法的。
tup1[0] = 100

3. 元组的遍历

python 复制代码
a_turple = (1, 2, 3, 4, 5)
for num in a_turple:
     print(num,end=" ")

4. 元组的内置函数

四、元组的应用场景

1.打包和解包操作。

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

python 复制代码
# 打包
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(解包的值不足)。

python 复制代码
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个或多个元素。还有在解包语法中,星号表达式只能出现一次。

python 复制代码
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函数返回的范围序列都可以使用解包语法。大家可以尝试运行下面的代码,看看会出现怎样的结果。

python 复制代码
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)

2.交换两个变量的值。

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

python 复制代码
a, b = b, a

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

python 复制代码
a, b, c = b, c, a

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

五、元组和列表的比较

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

  1. 元组是不可变类型,不可变类型更适合多线程环境,因为它降低了并发访问变量的同步化开销。关于这一点,我们会在后面讲解多线程的时候为大家详细论述。

  2. 元组是不可变类型,通常不可变类型在创建时间和占用空间上面都优于对应的可变类型 。我们可以使用sys模块的getsizeof函数来检查保存相同元素的元组和列表各自占用了多少内存空间。我们也可以使用timeit模块的timeit函数来看看创建保存相同元素的元组和列表各自花费的时间,代码如下所示。

    python 复制代码
    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)'))
  3. Python中的元组和列表是可以相互转换的,我们可以通过下面的代码来做到。

    python 复制代码
    # 将元组转换成列表
    info = ('骆昊', 175, True, '四川成都')
    print(list(info))       # ['骆昊', 175, True, '四川成都']
    # 将列表转换成元组
    fruits = ['apple', 'banana', 'orange']
    print(tuple(fruits))    # ('apple', 'banana', 'orange')

列表和元组都是容器型的数据类型 ,即一个变量可以保存多个数据。列表是可变数据类型元组是不可变数据类型,所以列表添加元素、删除元素、清空、排序等方法对于元组来说是不成立的。

相关推荐
2401_895521345 小时前
SpringBoot Maven快速上手
spring boot·后端·maven
disgare5 小时前
关于 spring 工程中添加 traceID 实践
java·后端·spring
ictI CABL5 小时前
Spring Boot与MyBatis
spring boot·后端·mybatis
小江的记录本7 小时前
【Linux】《Linux常用命令汇总表》
linux·运维·服务器·前端·windows·后端·macos
yhole10 小时前
springboot三层架构详细讲解
spring boot·后端·架构
香香甜甜的辣椒炒肉10 小时前
Spring(1)基本概念+开发的基本步骤
java·后端·spring
白毛大侠11 小时前
Go Goroutine 与用户态是进程级
开发语言·后端·golang
ForteScarlet11 小时前
从 Kotlin 编译器 API 的变化开始: 2.3.20
android·开发语言·后端·ios·开源·kotlin
大阿明11 小时前
SpringBoot - Cookie & Session 用户登录及登录状态保持功能实现
java·spring boot·后端
Binary-Jeff11 小时前
Spring 创建 Bean 的关键流程
java·开发语言·前端·spring boot·后端·spring·学习方法