python 序列类型 元组
元组定义
元组是不可变序列,通常用于储存异构数据的多项集(例如由 enumerate() 内置函数所产生的二元组)。 元组也被用于需要同构数据的不可变序列的情况(例如允许存储到 set 或 dict 的实例)。
元组是 Python 中的一种数据结构,类似于列表,但是元组是不可变的,意味着一旦创建,元组内的元素无法被修改、添加或删除。tuple 函数的作用是将一个可迭代对象(如列表、字符串或其他可迭代的对象)转换为元组。
元组构建方式
使用一对圆括号来表示空元组: ()
使用一个后缀的逗号来表示单元组: a, 或 (a,)
使用以逗号分隔的多个项: a, b, c or (a, b, c)
使用内置的 tuple(): tuple() 或 tuple(iterable)
请注意决定生成元组的其实是逗号而不是圆括号。 圆括号只是可选的,生成空元组或需要避免语法歧义的情况除外。例如,f(a, b, c) 是在调用函数时附带三个参数,而 f((a, b, c)) 则是在调用函数时附带一个三元组。
示例
# 空元祖创建
a = () # 一对圆括号来表示空元组
print(type(a)) # 输出:<class 'tuple'>
print(a) # 输出:()
# 单元素元组的创建
a = 5, # 加上逗号表示单元素元组
print(type(a)) # 输出:<class 'tuple'>
print(a) # 输出:(5,)
# 另一种方式是使用括号明确地标识单元素元组
b = (5,) # 使用括号和逗号表示单元素元组
print(type(b)) # 输出: <class 'tuple'>
print(b) # 输出:(5,)
# 多元素
a = 'a', 'b', 'c' # 多元素使用逗号分隔
print(type(a)) # 输出:<class 'tuple'>
print(a) # 输出:('a', 'b', 'c')
# 多元素另一种方式
a = ('a', 'b', 'c') # 多元素使用逗号分隔
print(type(a)) # 输出:<class 'tuple'>
print(a) # 输出:('a', 'b', 'c')
tuple([iterable])
tuple([iterable]) 可以接受一个可选参数 iterable,它可以是任何可迭代对象,如列表、字符串、集合等。如果没有提供参数,将返回一个空元组。
当 iterable 是一个元组时,tuple() 返回原始元组的拷贝。
当 iterable 是一个列表时,tuple() 将列表转换为元组。
当 iterable 是一个迭代器时,tuple() 将迭代器中的元素转换为元组。
当 iterable 是一个字符串时,tuple() 将字符串中每个字符转换为元组中的一个元素。
示例
# 将列表转换为元组
my_list = [1, 2, 3, 4, 5]
my_tuple = tuple(my_list)
print(my_tuple) # 输出:(1, 2, 3, 4, 5)
# 将字符串转换为元组
my_string = 'hello'
my_tuple = tuple(my_string)
print(my_tuple) # 输出:('h', 'e', 'l', 'l', 'o')
# 将集合转换为元组
my_set = {1, 2, 3}
my_tuple = tuple(my_set)
print(my_tuple) # 输出:(1, 2, 3)
# 复制元组
original_tuple = (1, 2, 3)
copied_tuple = tuple(original_tuple)
print(copied_tuple) # 输出:(1, 2, 3)
# 不传入任何参数,生成空元组
empty_tuple = tuple()
print(empty_tuple) # 输出:()
元组元素的访问
索引访问
通过索引访问元素:使用方括号 [] 和元素的索引(从0开始)来访问元组中的特定元素。
负数索引:可以使用负数索引来从元组末尾开始访问元素。例如,-1 表示最后一个元素,-2 表示倒数第二个元素,依此类推
正负索引不可以超界,否则引发异常IndexError。
# 创建一个元组
my_tuple = (1, 'apple', 3.14, ('nested', 'tuple'))
# 访问元组中的元素
print(my_tuple[0]) # 输出:1
print(my_tuple[2]) # 输出:3.14
# 使用负数索引访问元素
print(my_tuple[-1]) # 输出:('nested', 'tuple')
print(my_tuple[-2]) # 输出:3.14
# 访问嵌套元组中的元素
print(my_tuple[3][0]) # 输出: 'nested'
切片访问
使用切片操作符 : 可以从元组中获取一定范围的元素,语法为 tuple[start:stop:step]。
start 表示切片开始的位置(默认为0)。
stop 表示切片结束的位置(不包含该位置的元素)。
step 表示切片的步长(默认为1)。
# 创建一个元组
my_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
# 获取从第二个元素到第五个元素(不包含)的切片
slice1 = my_tuple[1:5]
print(slice1) # 输出: (2, 3, 4, 5)
# 获取从第一个元素开始到第八个元素(不包含),步长为2的切片
slice2 = my_tuple[:8:2]
print(slice2) # 输出: (1, 3, 5, 7)
# 获取倒数第三个元素到倒数第一个元素的切片
slice3 = my_tuple[-3:]
print(slice3) # 输出: (8, 9, 10)
元组查询
index(value, start, stop)
功能:index 函数用于查找特定元素在元组中首次出现的位置索引。
语法:index(value, start, stop),其中 value 是要查找的元素,start 是起始索引,stop 是结束索引。
时间复杂度: O(n),其中n是元组中的元素数量。
my_tuple = (2, 3, 4, 1, 4, 6)
print(my_tuple.index(4)) # 输出: 2
count(value)
功能:count 函数用于统计元组中指定元素出现的次数。
语法:count(value),其中 value 是要统计出现次数的元素。
时间复杂度: O(n),其中n是元组中的元素数量。
my_tuple = (2, 3, 4, 1, 4, 2)
print(my_tuple.count(2)) # 输出: 2
len(iterable)
功能:len 函数用于获取元组中的元素数量。
语法:len(iterable),其中 iterable 是要获取长度的元组。
时间复杂度: O(1)。元组的长度信息通常会被Python维护,因此获取长度是一个常数时间操作。
my_tuple = (2, 3, 4, 1, 4, 2)
print(len(my_tuple)) # 输出: 6
命名元组
namedtuple 是一个可以创建命名元组的工厂函数。命名元组是元组的一个子类,它允许给每个位置指定一个字段名,这样可以更容易地访问元组的各个部分。这对于管理结构化的数据非常有用,因为它允许你像访问对象的属性一样访问元组的字段。
namedtuple
语法: collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
typename 是你创建的命名元组子类的名称。
field_names 可以是一个由字段名称组成的字符串或字段名称的可迭代对象。
rename 控制是否自动调整无效字段名,默认为 False。
defaults 可以用于指定字段的默认值。
module 在 __repr__ 等特殊方法中使用,指定命名元组的模块名称。
返回值:返回一个新的元组子类,名为 typename 。这个新的子类用于创建类元组的对象,可以通过字段名来获取属性值,同样也可以通过索引和迭代获取值。
from collections import namedtuple
# 创建命名元组类型
Car = namedtuple('Car', ['brand', 'model', 'year'])
# 创建命名元组实例
my_car = Car('Toyota', 'Corolla', '2022')
# 访问命名元组字段
print(my_car.brand) # 输出:'Toyota'
print(my_car.model) # 输出:'Corolla'
print(my_car.year) # 输出:'2022'
from collections import namedtuple
# 创建命名元组类型
Car = namedtuple('Car', ['brand', 'model', 'year'])
# 使用字典创建包含车辆信息的字典
car_data = {'brand': 'Honda', 'model': 'Accord', 'year': '2023'}
# 使用解包运算符创建命名元组实例
new_car = Car(**car_data)
# 访问命名元组字段
print(new_car.brand) # 输出:'Honda'
print(new_car.model) # 输出:'Accord'
print(new_car.year) # 输出:'2023'
元组的使用场景
元组在需要不可变性、同时处理多个有序值、保护数据一致性等场景下非常有用。它们提供了一种轻量级、简单的数据结构,可以帮助简化代码并增强程序的可读性。
保护数据的完整性:元组是不可变的,一旦创建后就无法修改,因此适合用来存储那些不应该更改的数据,从而保护数据的完整性。
函数返回多个值:函数可以返回一个元组,以便一次性返回多个值。接收者可以通过解构操作同时获取这些返回值。
作为字典的键:由于元组是不可变的,可以作为字典的键使用,而列表则不行。这使得元组在需要使用不可变对象作为键的情况下非常方便。
用作函数参数:元组可以作为函数的参数传递,例如在需要传递多个参数且这些参数相关联时,将它们封装在一个元组中传递更加方便。
记录数据:元组可以用来表示记录型数据,例如二维坐标、日期时间等。
解构操作:通过元组的解构操作,可以方便地将元组中的值分配给多个变量。
集合运算:在集合运算中,元组可以作为集合的元素,例如在计算笛卡尔积时。
多值比较:通过元组的多值比较,可以方便地按多个条件排序对象。
参考文档
https://docs.python.org/zh-cn/3.12/library/stdtypes.html#/tuples
https://docs.python.org/zh-cn/3.12/library/collections.html#/namedtuple-factory-function-for-tuples-with-named-fields