在 Python 中,tuple(元组)是一种 有序的、不可变 的集合。与 list(列表)类似,它可以存储多个不同类型的元素,但不同点在于 tuple 一旦创建后,里面的元素就不能被修改、添加或删除。
特点
- 有序性:tuple 中的元素是有序排列的,可以通过索引来访问,如 tuple[0]。
- 不可变性:tuple 一旦创建,元素无法更改(无法增加、删除或改变元素值)。
- 使用小括号:tuple 使用小括号 () 来创建,元素之间用逗号隔开。
创建元组的方式
my_tuple = (1, 2, 3, \'a\', \'b\')
# 单个元素的元组(需要一个逗号)
single_element_tuple = (5,)
为什么单个元素的元组(需要一个逗号)?为了让 Python 确认你要创建的是一个单元素的元组,而不是普通的括号包裹数值,需要在单个元素后加逗号。
范例解释
#没有逗号的情况
single_element_tuple = (5)
print(type(single_element_tuple)) # 输出 <class \'int\'>
#加上逗号的情况
single_element_tuple = (5,)
print(type(single_element_tuple)) # 输出 <class \'tuple\'>
语法糖 自动被打包成一个 元组(tuple)
在 Python 中,当使用逗号分隔多个值时,这些值会自动被打包成一个元组(tuple),即使你不明确使用圆括号。
packed_tuple = 1, 2, 3 # 没有括号
print(packed_tuple) # (1, 2, 3)
print(type(packed_tuple))# <class \'tuple\'>
访问元组中的元素
my_tuple = (1, 2, 3, \'a\', \'b\')
print(my_tuple[0]) # 输出 1
print(my_tuple[3]) # 输出 \'a\'
不可变性
my_tuple = (1, 2, 3)
# my_tuple[0] = 10 # 这行会报错,因为元组不可修改
元组(Tuple)的常用操作
len() | 取得元组的长度 | len((1, 2, 3)) | 3 |
index() | 查找指定元素的索引值 | (1, 2, 3).index(2) | 1 |
count() | 计算指定元素出现的次数 | (1, 2, 2, 3).count(2) | 2 |
元组解包(Unpacking) | 将元组中的元素赋值给变数 | a, b, c = (1, 2, 3) | a=1, b=2, c=3 |
切片(Slicing) | 取得元组中的部分元素 | (1, 2, 3, 4)[1:3] | (2, 3) |
连接(Concatenation) | 连接两个或多个元组 | (1, 2) + (3, 4) | (1, 2, 3, 4) |
重复(Repetition) | 重复元组中的元素多次 | (\'a\', \'b\') * 2 | (\'a\', \'b\', \'a\', \'b\') |
成员检查(in) | 检查元素是否在元组中 | 2 in (1, 2, 3) | True |
比较(Comparison) | 比较两个元组的大小 | (1, 2, 3) > (1, 2, 1) | True |
迭代(Iteration) | 遍历元组中的所有元素 | for x in (1, 2, 3): print(x) | 1 2 3 |
元组解包(Unpacking)
想像元组是装东西的「盒子」,里面放了不同的三个数字。比如:1、2 和 3。
my_tuple = (1, 2, 3)
解包(Unpacking) 就像是你把这些东西从盒子里拿出来,分给不同的人(变数)。比如:
a, b, c = my_tuple
这里,a 得到了 1,b 得到了 2,c 得到了 3。就像是你把盒子里的东西一个一个分配给不同的变数。
所以元组解包(Unpacking) 有点像是javascript的解构概念?
是的,元组解包(Unpacking) 在 Python 中的概念,确实与 JavaScript 的解构赋值(Destructuring Assignment) 非常相似。两者都涉及将数组或对象(在 JavaScript 中)或元组(在 Python 中)的值拆解出来,并赋值给不同的变数。
比较范例
Python 中的元组解包(Unpacking)
my_tuple = (1, 2, 3)
a, b, c = my_tuple
print(a, b, c) # 1 2 3
JavaScript 中的解构赋值(Destructuring Assignment)
const myArray = [1, 2, 3];
const [a, b, c] = myArray;
console.log(a, b, c); // 1 2 3
主要类似之处:
多个值的分配:两者都从多个值的容器(元组或数组)中,将每个元素提取出来,并分配给不同的变数。简化代码:这些语法让我们不用手动逐个提取元素,简化了代码的书写。
问题:如何交换两个变数的值?
Python 的简单方法Python 使用了元组这个概念,类似于打包礼物的包裹。
- 首先,它把 b 和 a 这两个东西(香蕉和苹果)包在一起变成一个包裹packing。
- 然后它打开这个包裹unpacking,分别把里面的香蕉给 a,苹果给 b。
a = apple
b = banana
# 这一步发生了 tuple packing 和 unpacking
a, b = banana, apple #右边的值(香蕉和苹果)包在一起变成一个包裹。(banana, apple )
# 现在 a 和 b 的值已经交换
print(a) # 10
print(b) # 5
使用*解包:更灵活的资料处理
在 Python 中,*号在解包(unpacking)时扮演着非常重要的角色,它让我们可以更灵活地处理可迭代对象(如列表、元组等)。
基本用法
将可迭代对象的元素分配给多个变数:当我们知道可迭代对象的元素个数时,可以直接将元素一一分配给变数。但当元素个数不确定或想将多余的元素收集到一个变数中时,* 就派上用场了
numbers = [1, 2, 3, 4, 5]
a, b, *c = numbers
print(a) # 输出 1
print(b) # 输出 2
print(c) # 输出 [3, 4, 5]
在这个例子中,*c 表示将剩余的元素收集到列表 c 中。
将字典解包:
* 也可以用于解包字典。
person = {\'name\': \'Alice\', \'age\': 30, \'city\': \'New York\'}
name, *rest = person.items()
print(name) # 输出 (\'name\', \'Alice\')
print(rest) # 输出 [(\'age\', 30), (\'city\', \'New York\')]
进阶用法
- 函数参数:
- * 可以用来表示可变长度的位置参数。
def greet(*names):
for name in names:
print(f"Hello, {name}!")
greet(\'Alice\', \'Bob\', \'Charlie\')
- 函数返回值:
- * 可以用来将可迭代对象的元素拆开作为函数的返回值。
def split_list(numbers):
return numbers[:2], *numbers[2:]
a, *b = split_list([1, 2, 3, 4])
print(a) # 输出 [1, 2]
print(b) # 输出 [3, 4]
注意事项:*只能出现在赋值语句的左侧或函数定义的参数列表中。
什么是 Mutable objects in tuples?
在 Python 中,元组(tuple)是不可变的immutable,这意味着一旦创建了元组,里面的元素就不能被修改或重新赋值。然而,元组可以包含可变的对象,这些可变对象可以在元组内被修改,尽管元组本身仍然是不可变的。这就是可变对象在元组中的情况。
例子解释:
-
元组本身不可变:元组中的每个元素的值和位置不能被改变。例如,my_tuple = (1, 2, 3) 创建了一个包含数字 1、2 和 3 的元组。你不能改变元组中的数字,像 my_tuple[0] = 5 这样的操作会报错。
-
元组中的可变对象:虽然元组本身不可变,但如果元组内包含可变对象,如列表或字典,这些对象的内容是可以改变的。
my_tuple = (1, 2, [3, 4])
# 尝试改变元组内的列表
my_tuple[2].append(5)
print(my_tuple) #(1, 2, [3, 4, 5])
在这里,my_tuple[2] 是一个列表 [3, 4],虽然元组是不可变的,但这个列表是可变的,所以我们可以对列表进行修改,像 append(5) 这样操作。
哪些可以当作字典的 key?
在 Python 中,字典的 key 必须是不可变(immutable)的物件。这意味着可以作为字典 key 的物件类型包括:
- 字串(string)
- 整数(integer)
- 浮点数(float)
- 元组(tuple),但元组中的元素也必须是不可变的。
现在来看两个例子:(\'tom\', [14, 23, 26])这个元组内包含了一个可变的列表 [14, 23, 26]。由于列表是可变的,这个元组不能作为字典的 key。
[\'string\', (15, 16)]这是个列表,而列表本身是可变的,所以它不能作为字典的 key。
哪些可以当作字典的 key?
- (\'tom\', [14, 23, 26]):❌ 不可以,因为包含可变的列表。
- [\'string\', (15, 16)]:❌ 不可以,因为列表是可变的。
- 如果你要用元组作为字典的 key,该元组内的所有元素都必须是不可变的,例如 (\'tom\', (14, 23, 26)) 就是合法的字典 key,因为元组内的所有元素都是不可变的。