Python通关秘籍(五)数据结构——元组
前文复习
五、数据结构
5.1 列表(List
)
列表是一种有序的可变数据集合,可以包含不同类型的元素。
5.2 元组(Tuple
)
元组是一种有序的不可变数据集合,通常用于存储一组相关的值。
5.2.1 元组的定义与创建
-
使用圆括号
通过在圆括号内放置多个元素,并用逗号分隔来创建元组。
# 创建一个包含多个元素的元组 my_tuple = (1, 'apple', 3.14) print(my_tuple)
-
省略圆括号
在很多情况下,圆括号可以省略,只要元素之间用逗号分隔,Python 也会将其识别为元组。
# 省略圆括号创建元组 my_tuple = 1, 'apple', 3.14 print(my_tuple)
-
创建单个元素元组
创建只包含一个元素的元组时,必须在元素后面添加逗号,否则 Python 会将其视为普通变量。
# 正确创建单元素元组 single_element_tuple = (1,) print(single_element_tuple) # 这将被视为整数,而不是元组 not_a_tuple = (1) print(type(not_a_tuple))
5.2.2 元组的特点
-
不可变
元组的最大特点就是不可变性,一旦创建,元组中的元素不能被修改、添加或删除。
my_tuple = (1,2,3) # 下边代码会抛出TypeError: 'tuple'object does not support item assignment 错误 # my_tuple[0] = 10
这种不可变性使得元组在某些场景下具有更高的安全性,比如在多线程环境中,元组的数据不会被意外修 改,从而保证了数据的一致性。
-
有序性
元组中的元素是有序的,这一点与列表相同。我们可以通过索引来访问元组中的特定元素, 索引从 0 开始,与列表索引方式相同,支持正负索引。
my_tuple = (1, 2, 3, 4, 5) print(my_tuple[2]) # 输出: 3 print(my_tuple[-1]) # 输出: 5
-
内存占用和性能优势
由于元组是不可变的,Python 在内存管理上对元组进行了优化,元组通常占用更少的内存空间。在处理大量数据时,使用元组可以节省内存资源,提高程序的运行效率。例如,当存储一些常量数据或固定配置时,使用元组可以减少内存开销,提升程序性能。同时,元组的不可变性使得 Python 在创建元组时可以进行一些优化,元组的创建速度比列表略快,尤其是在创建包含少量元素的元组时,这种速度优势更为明显。
元组在迭代时的性能略优于列表,因为其不可变的特性使得 Python 解释器在某些情况下可以进行更优化的处理。不过,这种性能差异在大多数普通应用场景下并不明显,只有在处理大量数据和高频率迭代时才可能体现出来。
5.2.3 元组的操作
1. 访问元组元素
-
使用索引
与列表一样,元组的元素可以通过索引访问。索引从 0 开始,负数索引从元组末尾开始计数。
my_tuple = (1, 'apple', 3.14) # 访问第一个元素 first_element = my_tuple[0] print(first_element) # 访问最后一个元素 last_element = my_tuple[-1] print(last_element)
-
使用切片
可以使用切片从元组中获取子元组。切片的语法为
tuple[start:stop:step]
,其中start
是起始索引(包含),stop
是结束索引(不包含),step
是步长。my_tuple = (1, 2, 3, 4, 5) # 获取索引1到3(不包含)的子元组 sub_tuple = my_tuple[1:3] print(sub_tuple) # 获取从索引0开始,每隔一个元素的子元组 every_other_tuple = my_tuple[::2] print(every_other_tuple)
-
统计元素出现次数
count()
方法:用于统计元组中某个元素出现的次数。my_tuple = (1, 2, 2, 3, 2) count_of_2 = my_tuple.count(2) print(f"元素2出现的次数: {count_of_2}")
-
查找元组中某个元素首次出现的索引位置
index()
方法:用于查找元组中某个元素首次出现的索引位置,如果元素不存在则抛出ValueError
异常。my_tuple = (1, 2, 3, 2) try:index_of_3 = my_tuple.index(3)print(f"元素3的索引: {index_of_3}") except ValueError as e:print(f"错误: {e}")
2. 元组的连接与重复
-
使用
+
连接两个元组可以使用 + 运算符将两个元组连接起来,形成一个新的元组。
tuple1 = (1, 2) tuple2 = (3, 4) print(tuple1 + tuple2) # 输出: (1, 2, 3, 4)
-
使用
*
将元组的元素重复使用 * 运算符将一个元组 重复指定的次数,生成一个新的元组。
tuple1 = (1, 2) print(tuple1 * 3) # 输出: (1, 2, 1, 2, 1, 2)
3. 成员判断
使用in
或not in
关键字可以判断一个元素是否存在于元组中,返回布尔值。
my_tuple = (1, 2, 3, 4, 5)
print(3 in my_tuple) # 输出: True
print(6 not in my_tuple) # 输出: True
4. 元组解包
元组解包是指将元组中的元素解包到多个变量中。
my_tuple = (1, 'apple')
# 将元组的元素解包到两个变量中
num, fruit = my_tuple
print(num)
print(fruit)
甚至可以在解包时使用 *
运算符收集多余的元素到一个列表中。
my_tuple = (1, 2, 3, 4)
first, *middle, last = my_tuple
print(first)
print(middle)
print(last)
5. 元组与其他数据结构的相互转换
-
元组转列表:使用
list()
函数可以将元组转换为列表,这样就可以利用列表的可变性对元素进行修改。my_tuple = (1, 2, 3) my_list = list(my_tuple) my_list.append(4) print(my_list)
-
列表转元组:使用
tuple()
函数可以将列表转换为元组,从而确保数据的不可变性。my_list = [1, 2, 3] my_tuple = tuple(my_list) print(my_tuple)
-
元组与集合的转换:集合是无序且元素唯一的,将元组转换为集合会去除重复元素,转换回元组时顺序可能改变。
my_tuple = (1, 2, 2, 3) my_set = set(my_tuple) print(my_set) new_tuple = tuple(my_set) print(new_tuple)
5.2.4 应用场景
-
存储坐标点
在图形编程或数学计算中,经常需要表示二维或三维坐标点。使用元组可以简洁地存储 坐标信息,并且由于其不可变性,保证了坐标值不会被意外修改。例如:
point_2d = (10, 20) # 表示二维坐标点 (x, y) point_3d = (10, 20, 30) # 表示三维坐标点 (x, y, z)
-
函数返回多个值
Python 函数可以返回多个值,这些值会被自动封装成一个元组返回。例如,定义一 个函数计算两个数的和与积:
def calculate(x, y): return x + y, x * y result = calculate(3, 4) print(result) # 输出: (7, 12),返回的是一个元组 sum_result, product_result = result # 可以通过解包元组获取返回值 print(sum_result) # 输出: 7 print(product_result) # 输出: 12
-
存储数据库记录
在与数据库交互时,从数据库查询返回的一条记录通常可以用元组来表示。元组的 不可变性确保了记录的完整性,避免在程序处理过程中数据被无意修改。例如,假设从数据库中查询 一个用户的信息,包括用户 ID、姓名和年龄:
user_info = (1, "Alice", 25) # 表示一条用户信息记录
-
作为字典的键
由于元组是不可变的,它可以作为字典的键,而列表则不能。这在需要使用多个值作 为键来创建字典时非常有用。例如,在一个地图应用中,可以使用元组(纬度,经度)作为键来存储地点信息:
locations = { (37.7749, -122.4194): "San Francisco", (40.7128, -74.0060): "New York"} print(locations[(37.7749, -122.4194)]) # 输出: San Francisco
5.2.4 元组相关函数总结
函数/方法 | 分类 | 参数 | 描述 |
---|---|---|---|
count(value) | 元组方法 | value :要统计的元素值 | 返回指定元素在元组中出现的次数。例如对于元组 t = (10, 20, 20, 30, 20) ,t.count(20) 返回 3 。 |
index(value[, start[, end]]) | 元组方法 | value :要查找的元素值start :可选参数,起始搜索位置,默认为 0 end :可选参数,结束搜索位置(不包含该位置) | 返回指定元素在元组中首次出现的索引。如果元素不存在会引发 ValueError 异常。例如对于元组 t = (10, 20, 30, 20) ,t.index(20) 返回 1 ;t.index(20, 2) 返回 3 。 |
len(tuple) | 内置函数 | tuple :要计算元素数量的元组 | 返回元组中元素的个数。例如,对于元组 t = (1, 2, 3) ,len(t) 返回 3 。 |
sorted(iterable, key=None, reverse=False) | 内置函数 | iterable :要进行排序的元组key=None :可选参数,是一个函数,用于指定排序的依据。该函数接受元组中的一个元素作为参数,并返回一个用于比较的值。例如,若要按元素的绝对值排序,可设 key = abs reverse=False :可选参数,布尔值。True 表示降序排序,False 表示升序排序,默认值为 False | 对元组中的元素进行排序,并返回一个新的已排序列表。原元组保持不变。例如,对于元组 t = (3, 1, 2) ,sorted(t) 返回 [1, 2, 3] ;若使用 sorted(t, reverse = True) ,则返回 [3, 2, 1] 。 |
max(iterable, *[, key, default]) | 内置函数 | iterable :要从中找出最大值的元组key=None :可选参数,是一个函数,用于指定比较的依据。该函数接受元组中的一个元素作为参数,并返回一个用于比较的值。例如,对于包含字典的元组,要根据字典中某个键的值来比较,可设 key = lambda x: x['key_name'] default :可选参数,当元组为空时返回的默认值。如果不提供此参数且元组为空,会引发 ValueError | 返回元组中的最大元素。例如,对于元组 t = (1, 3, 2) ,max(t) 返回 3 。当元组包含自定义对象时,若未指定 key ,对象需实现可比较的方法;若指定了 key ,则按 key 函数返回值进行比较。当元组为空且未提供 default 时会报错。 |
min(iterable, *[, key, default]) | 内置函数 | iterable :要从中找出最小值的元组key=None :同 max 函数中的 key 参数,用于指定比较的依据default :可选参数,当元组为空时返回的默认值。如果不提供此参数且元组为空,会引发 ValueError | 返回元组中的最小元素。例如,对于元组 t = (1, 3, 2) ,min(t) 返回 1 。与 max 函数类似,当元组包含自定义对象时,比较方式受 key 参数影响。当元组为空且未提供 default 时会报错。 |
sum(iterable,start = 0) | 内置函数 | iterable :只包含数字(整数、浮点数等)的元组start = 0 :可选参数,指定累加的起始值,默认为 0 | 计算元组中所有数字元素的总和。例如,对于元组 t = (1, 2, 3) ,sum(t) 返回 6 (即 1 + 2 + 3 );若设置 start = 5 ,即 sum(t, 5) ,则返回 11 (即 5 + 1 + 2 + 3 )。 |
all(iterable) | 内置函数 | iterable :要检查的元组 | 如果元组中的所有元素都为真值(或元组为空),则返回 True ,否则返回 False 。例如,对于元组 t = (1, True, 'a') ,all(t) 返回 True ;对于元组 t = (0, True) ,all(t) 返回 False 。 |
any(iterable) | 内置函数 | iterable :要检查的元组 | 如果元组中至少有一个元素为真值,则返回 True ;如果元组为空或所有元素都为假值,则返回 False 。例如,对于元组 t = (0, False, '') ,any(t) 返回 False ;对于元组 t = (0, True, '') ,any(t) 返回 True 。 |
tuple(iterable) | 内置函数 | iterable=None :可选参数,一个可迭代对象,如列表、集合、字符串等。如果不提供参数,将返回一个空元组 | 将可迭代对象转换为元组。例如,对于列表 l = [1, 2, 3] ,tuple(l) 返回 (1, 2, 3) ;对于字符串 s = "abc" ,tuple(s) 返回 ('a', 'b', 'c') ;若不传入参数,tuple() 返回 () 。 |
enumerate(iterable, start = 0) | 内置函数 | iterable :要进行枚举的元组start = 0 :可选参数,指定枚举的起始索引值,默认为 0 | 将元组组合为一个索引序列,返回一个枚举对象。该对象的每个元素是一个包含索引和元组元素的元组。例如,对于元组 t = ('a', 'b', 'c') ,enumerate(t) 得到的枚举对象在迭代时会依次返回 (0, 'a') ,(1, 'b') ,(2, 'c') ;若设置 start = 1 ,即 enumerate(t, 1) ,则会依次返回 (1, 'a') ,(2, 'b') ,(3, 'c') 。 |
zip(*iterable) | 内置函数 | *iterables :多个可迭代对象(至少两个),通常为元组 | 将多个元组中对应位置的元素打包成一个个元组,然后返回由这些元组组成的迭代器。例如,对于元组 t1 = (1, 2, 3) 和 t2 = ('a', 'b', 'c') ,zip(t1, t2) 返回一个迭代器,其内容为 (1, 'a') ,(2, 'b') ,(3, 'c') 。如果各个元组长度不一致,以最短的元组长度为准。例如,若 t1 = (1, 2, 3) ,t2 = ('a', 'b') ,则 zip(t1, t2) 返回的迭代器内容为 (1, 'a') ,(2, 'b') 。 |
学习秘籍
1️⃣ 多写代码少死记(动手比看书重要!)
2️⃣ 善用print()
调试(观察程序每一步)
3️⃣ 错误是朋友(读懂报错信息你就赢了50%)