← 返回首页
🔒

元组与不可变序列

📂 python ⏱ 3 min 438 words

元组的创建

元组(tuple)是不可变的有序序列,用圆括号 () 表示:

# 创建元组
colors = ("红", "绿", "蓝")
numbers = (1, 2, 3, 4, 5)
mixed = (1, "hello", 3.14, True)

# 单元素元组(注意逗号)
single = (42,)     # 这是元组
not_tuple = (42)   # 这只是整数42

# 省略括号(元组打包)
point = 3, 4, 5
print(type(point))  # <class 'tuple'>

# 空元组
empty = ()
empty2 = tuple()

# 从其他类型转换
list_to_tuple = tuple([1, 2, 3])
str_to_tuple = tuple("Hello")

元组的基本操作

元组支持索引、切片、遍历等操作:

fruits = ("苹果", "香蕉", "橘子", "西瓜", "葡萄")

# 索引
print(fruits[0])    # 苹果
print(fruits[-1])   # 葡萄

# 切片
print(fruits[1:3])  # ('香蕉', '橘子')
print(fruits[::2])  # ('苹果', '橘子', '葡萄')

# 遍历
for fruit in fruits:
    print(fruit)

# 长度
print(len(fruits))  # 5

# 检查成员
print("苹果" in fruits)  # True

元组的方法

元组只有两个内置方法,因为它们是不可变的:

numbers = (1, 2, 3, 2, 4, 2, 5)

# count() - 统计出现次数
print(numbers.count(2))  # 3

# index() - 查找元素位置
print(numbers.index(4))  # 4

元组 vs 列表

特性 元组 列表
可变性 不可变 可变
语法 () []
性能 更快,内存占用更少 较慢
可作为字典键
用途 固定数据集合 需要修改的数据集合
# 元组不可变
t = (1, 2, 3)
# t[0] = 99  # TypeError!

# 列表可变
l = [1, 2, 3]
l[0] = 99   # 正确

元组解包

元组解包是将元组的元素同时赋给多个变量:

# 基本解包
point = (3, 4)
x, y = point
print(f"x={x}, y={y}")  # x=3, y=4

# 交换变量(利用元组解包)
a, b = 1, 2
a, b = b, a
print(a, b)  # 2 1

# 多变量解包
name, age, city = "小明", 25, "北京"
print(f"{name}今年{age}岁,住在{city}")

# 使用 * 收集剩余元素
first, *rest = (1, 2, 3, 4, 5)
print(first)  # 1
print(rest)   # [2, 3, 4, 5]

*head, last = (1, 2, 3, 4, 5)
print(head)  # [1, 2, 3, 4]
print(last)  # 5

first, *middle, last = (1, 2, 3, 4, 5)
print(first)   # 1
print(middle)  # [2, 3, 4]
print(last)    # 5

元组的实际应用

函数返回多个值

def get_min_max(numbers):
    return min(numbers), max(numbers)

minimum, maximum = get_min_max([3, 1, 4, 1, 5, 9, 2, 6])
print(f"最小值: {minimum}, 最大值: {maximum}")

def divide(a, b):
    if b == 0:
        return None, "除数不能为零"
    return a / b, "计算成功"

result, message = divide(10, 3)
print(f"{result:.2f} - {message}")

作为字典的键

# 元组可以作为字典键(因为不可变)
locations = {
    (39.9, 116.4): "北京",
    (31.2, 121.5): "上海",
    (23.1, 113.3): "广州"
}

print(locations[(39.9, 116.4)])  # 北京

# 列表不能作为字典键
# { [1, 2]: "value" }  # TypeError!

作为字典项

# 元组常用于表示记录
students = [
    ("小明", 85),
    ("小红", 92),
    ("小刚", 78),
    ("小丽", 95)
]

for name, score in students:
    print(f"{name}: {score}分")

函数参数解包

def greet(name, age, city):
    print(f"你好,我是{name},今年{age}岁,来自{city}")

info = ("小明", 25, "北京")
greet(*info)  # 使用 * 解包元组作为参数

命名元组

Python标准库提供了命名元组,增加可读性:

from collections import namedtuple

# 定义命名元组
Point = namedtuple("Point", ["x", "y"])
Student = namedtuple("Student", "name age score")

# 使用
p = Point(3, 4)
print(p.x, p.y)  # 3 4

s = Student("小明", 25, 95)
print(f"{s.name}的成绩是{s.score}")

元组的性能优势

import sys

# 内存对比
list_example = [1, 2, 3, 4, 5]
tuple_example = (1, 2, 3, 4, 5)

print(sys.getsizeof(list_example))  # 104 字节
print(sys.getsizeof(tuple_example))  # 80 字节

# 创建速度对比
import timeit

list_time = timeit.timeit("[1, 2, 3, 4, 5]", number=1000000)
tuple_time = timeit.timeit("(1, 2, 3, 4, 5)", number=1000000)

print(f"列表: {list_time:.4f}秒")
print(f"元组: {tuple_time:.4f}秒")

何时使用元组

总结

元组是不可变的有序序列,虽然功能比列表少,但在特定场景下更高效、更安全。理解元组与列表的区别,能帮助你选择合适的数据结构。下一节我们将学习字典——Python中最重要的映射类型。