python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python元组(Tuple)高级用法

Python元组(Tuple)全部高级用法大全

作者:yuanpan

这段文章详细讲解了Python元组的用法,从基础到高级技巧,涵盖创建、解包、嵌套、与列表字典集合的转换等,还强调了元组在表示固定数据、防止误改、作为字典键等方面的优势,适合Python新手理解和掌握,需要的朋友可以参考下

很多 Python 新手刚学元组时,第一反应是:

元组不就是不能修改的列表吗?

这个理解没错,但只说对了一半。元组确实和列表很像,都能存多个数据;但元组在实际开发里还有很多常见用法,比如函数返回多个值多变量赋值数据解包作为字典键保存配置常量防止数据被误改等。

这篇文章用大白话把 Python 元组从基础到高级完整讲一遍。每个知识点都配有可运行代码、示例数据、运行结果和实际使用场景,适合 Python 新手收藏复盘。

1. 先回顾:什么是元组?

元组英文叫 tuple,它可以保存多个数据。

最常见写法是用小括号 ()

# 创建一个元组
person = ("小王", 18, "Python")

print(person)
print(type(person))

运行结果:

('小王', 18, 'Python')
<class 'tuple'>

你可以把元组理解成一个固定内容的数据包。创建好以后,里面的元素不能被直接修改。

person = ("小王", 18, "Python")

print(person[0])
print(person[1])
print(person[2])

运行结果:

小王
18
Python

实际使用场景:

新手先记住一句话:

元组适合存一组固定数据,列表适合存一组经常变化的数据。

2. 元组 VS 列表:核心区别

元组和列表很像,但它们最大的区别是:

对比项元组 tuple列表 list
写法("A", "B")["A", "B"]
是否可修改不可直接修改可以修改
常用场景固定数据、配置、函数返回值增删改数据
能否作为字典键满足条件时可以不可以
语义数据不希望被改数据后续可能变化

看代码更直观:

# 列表可以修改
names_list = ["小王", "小李"]
names_list[0] = "小张"
print(names_list)

# 元组不能直接修改
names_tuple = ("小王", "小李")
print(names_tuple)

运行结果:

['小张', '小李']
('小王', '小李')

如果你强行修改元组,会报错:

names_tuple = ("小王", "小李")

names_tuple[0] = "小张"

运行结果:

TypeError: 'tuple' object does not support item assignment

实际使用场景:

新手避坑:

3. 单元素元组正确写法与避坑

这是新手最容易踩的坑。

很多人以为这样就是单元素元组:

value = ("Python")

print(value)
print(type(value))

运行结果:

Python
<class 'str'>

它不是元组,而是字符串。因为小括号在这里只是普通分组。

单元素元组必须加逗号。

value = ("Python",)

print(value)
print(type(value))

运行结果:

('Python',)
<class 'tuple'>

数字也一样:

a = (100)
b = (100,)

print(type(a))
print(type(b))

运行结果:

<class 'int'>
<class 'tuple'>

实际使用场景:

新手避坑:

4. 元组可以不写小括号吗?

可以。Python 里真正决定元组的,很多时候是逗号。

point = 10, 20

print(point)
print(type(point))

运行结果:

(10, 20)
<class 'tuple'>

这也是元组。

不过新手建议先写小括号,因为更清楚:

point = (10, 20)

print(point)

运行结果:

(10, 20)

实际使用场景:

新手避坑:

5. 元组解包:一次取出多个值

元组解包就是把元组里的值,一次性分给多个变量。

person = ("小王", 18, "Python")

name, age, skill = person

print(name)
print(age)
print(skill)

运行结果:

小王
18
Python

可以理解成:

name  接收 "小王"
age   接收 18
skill 接收 "Python"

实际使用场景:

对比一下不用解包的写法:

person = ("小王", 18, "Python")

print(person[0])
print(person[1])
print(person[2])

运行结果:

小王
18
Python

虽然也能用,但 person[0]person[1] 对新手来说不够直观。解包后变量名更清楚。

新手避坑:

错误示例:

person = ("小王", 18, "Python")

name, age = person

运行结果:

ValueError: too many values to unpack (expected 2)

原因是右边有 3 个值,左边只有 2 个变量,接不住。

6. 多变量赋值:优雅交换变量

Python 里可以用元组思想做多变量赋值。

a, b = 10, 20

print(a)
print(b)

运行结果:

10
20

最经典的用法是交换两个变量:

a = 10
b = 20

# 交换 a 和 b 的值
a, b = b, a

print(a)
print(b)

运行结果:

20
10

实际使用场景:

示例:同时保存坐标。

x, y = 100, 200

print(f"x 坐标:{x}")
print(f"y 坐标:{y}")

运行结果:

x 坐标:100
y 坐标:200

新手避坑:

7. 星号 * 不定长解包

如果元组里的元素数量不固定,可以用星号 * 接收多余的元素。

scores = (90, 85, 70, 60, 100)

first, *middle, last = scores

print(first)
print(middle)
print(last)

运行结果:

90
[85, 70, 60]
100

注意:*middle 接收到的是一个列表,不是元组。

再看一个只取前两个,其余打包的例子:

data = ("小王", "Python", "北京", "后端开发")

name, skill, *others = data

print(name)
print(skill)
print(others)

运行结果:

小王
Python
['北京', '后端开发']

实际使用场景:

新手避坑:

错误示例:

nums = (1, 2, 3, 4)

*left, *right = nums

运行结果:

SyntaxError: multiple starred expressions in assignment

正确写法:

nums = (1, 2, 3, 4)

first, *rest = nums

print(first)
print(rest)

运行结果:

1
[2, 3, 4]

8. 忽略不需要的值:用下划线 _

有些值你不想用,可以用 _ 接住。

person = ("小王", 18, "Python")

name, _, skill = person

print(name)
print(skill)

运行结果:

小王
Python

这里 _ 表示这个值我不关心。

实际使用场景:

示例:

def get_user_info():
    return ("小王", 18, "北京")

name, _, city = get_user_info()

print(name)
print(city)

运行结果:

小王
北京

新手避坑:

a, _ = (10, 20)

print(_)

运行结果:

20

9. 元组嵌套使用

元组里面还可以放元组,这叫嵌套元组。

student = ("小王", (90, 85, 88), "一班")

print(student)

运行结果:

('小王', (90, 85, 88), '一班')

这个数据可以理解为:

学生姓名:小王
成绩:90, 85, 88
班级:一班

实际使用场景:

示例:多个坐标点。

points = ((0, 0), (10, 20), (30, 40))

print(points)

运行结果:

((0, 0), (10, 20), (30, 40))

新手避坑:

10. 嵌套元组取值

嵌套元组取值,就是一层一层用下标。

student = ("小王", (90, 85, 88), "一班")

name = student[0]
scores = student[1]
english_score = student[1][1]

print(name)
print(scores)
print(english_score)

运行结果:

小王
(90, 85, 88)
85

student[1][1] 的意思是:

student[1]    先拿到 (90, 85, 88)
student[1][1] 再拿这个元组里的第 2 个元素

还可以配合解包:

student = ("小王", (90, 85, 88), "一班")

name, (math_score, english_score, chinese_score), class_name = student

print(name)
print(math_score)
print(english_score)
print(chinese_score)
print(class_name)

运行结果:

小王
90
85
88
一班

实际使用场景:

新手避坑:

11. 元组与列表互相转换

元组可以转列表,列表也可以转元组。

names_tuple = ("小王", "小李", "小张")
names_list = list(names_tuple)

print(names_list)
print(type(names_list))

运行结果:

['小王', '小李', '小张']
<class 'list'>

列表转元组:

names_list = ["小王", "小李", "小张"]
names_tuple = tuple(names_list)

print(names_tuple)
print(type(names_tuple))

运行结果:

('小王', '小李', '小张')
<class 'tuple'>

实际使用场景:

示例:修改元组内容的常见思路。

colors = ("red", "green", "blue")

# 元组不能直接改,先转成列表
colors_list = list(colors)
colors_list[1] = "yellow"

# 改完再转回元组
colors = tuple(colors_list)

print(colors)

运行结果:

('red', 'yellow', 'blue')

新手避坑:

12. 元组与字典互相转换

元组经常和字典配合使用,尤其是二元组。

二元组列表可以转成字典:

pairs = (("name", "小王"), ("age", 18), ("skill", "Python"))

user = dict(pairs)

print(user)

运行结果:

{'name': '小王', 'age': 18, 'skill': 'Python'}

字典也可以转成由键值对组成的元组:

user = {"name": "小王", "age": 18, "skill": "Python"}

items_tuple = tuple(user.items())

print(items_tuple)

运行结果:

(('name', '小王'), ('age', 18), ('skill', 'Python'))

实际使用场景:

新手避坑:

错误示例:

pairs = (("name", "小王", "多余字段"), ("age", 18))

user = dict(pairs)

运行结果:

ValueError: dictionary update sequence element #0 has length 3; 2 is required

13. 元组与集合互相转换

元组转集合可以去重。

nums = (1, 2, 2, 3, 3, 3)

unique_nums = set(nums)

print(unique_nums)

运行结果:

{1, 2, 3}

集合转元组:

nums_set = {3, 1, 2}

nums_tuple = tuple(nums_set)

print(nums_tuple)

运行结果示例:

(1, 2, 3)

注意:集合本身没有固定顺序,不同环境下输出顺序可能不一样。

如果你想稳定排序,可以这样:

nums = (3, 1, 2, 2, 3)

result = tuple(sorted(set(nums)))

print(result)

运行结果:

(1, 2, 3)

实际使用场景:

新手避坑:

14. 元组拼接:用 + 合并

元组可以用 + 拼接。

base_info = ("小王", 18)
extra_info = ("Python", "北京")

user_info = base_info + extra_info

print(user_info)

运行结果:

('小王', 18, 'Python', '北京')

实际使用场景:

新手避坑:

a = (1, 2)
b = (3, 4)
c = a + b

print(a)
print(b)
print(c)

运行结果:

(1, 2)
(3, 4)
(1, 2, 3, 4)

如果频繁拼接大量数据,不建议反复用 +,可以先用列表收集,最后转元组。

15. 元组重复:用 * 快速生成固定数据

元组可以用 * 重复。

flags = ("未处理",) * 5

print(flags)

运行结果:

('未处理', '未处理', '未处理', '未处理', '未处理')

注意单元素元组还是要写逗号:("未处理",)

实际使用场景:

示例:

default_scores = (0,) * 4

print(default_scores)

运行结果:

(0, 0, 0, 0)

新手避坑:

wrong = ("未处理") * 3
right = ("未处理",) * 3

print(wrong)
print(right)

运行结果:

未处理未处理未处理
('未处理', '未处理', '未处理')

16. 快速合并技巧:星号展开多个元组

除了 +,还可以用星号 * 展开元组,再重新打包。

a = (1, 2)
b = (3, 4)
c = (5, 6)

result = (*a, *b, *c)

print(result)

运行结果:

(1, 2, 3, 4, 5, 6)

这种写法在需要同时插入新元素时很方便:

old_data = ("小王", 18)

new_data = (*old_data, "Python", "北京")

print(new_data)

运行结果:

('小王', 18, 'Python', '北京')

实际使用场景:

新手避坑:

17. zip() 搭配元组批量配对数据

zip() 可以把多个序列按位置配对,返回一组一组的元组。

names = ("小王", "小李", "小张")
scores = (90, 85, 88)

for item in zip(names, scores):
    print(item)

运行结果:

('小王', 90)
('小李', 85)
('小张', 88)

也可以直接解包:

names = ("小王", "小李", "小张")
scores = (90, 85, 88)

for name, score in zip(names, scores):
    print(f"{name} 的成绩是 {score}")

运行结果:

小王 的成绩是 90
小李 的成绩是 85
小张 的成绩是 88

实际使用场景:

示例:字段名和值转字典。

fields = ("name", "age", "skill")
values = ("小王", 18, "Python")

user = dict(zip(fields, values))

print(user)

运行结果:

{'name': '小王', 'age': 18, 'skill': 'Python'}

新手避坑:

names = ("小王", "小李", "小张")
scores = (90, 85)

print(list(zip(names, scores)))

运行结果:

[('小王', 90), ('小李', 85)]

小张 没有对应成绩,所以被丢掉了。

18. enumerate() 结合元组遍历

enumerate() 可以在遍历元组时,同时拿到序号和值。

skills = ("Python", "SQL", "Linux")

for index, skill in enumerate(skills):
    print(index, skill)

运行结果:

0 Python
1 SQL
2 Linux

如果想让序号从 1 开始:

skills = ("Python", "SQL", "Linux")

for index, skill in enumerate(skills, start=1):
    print(f"{index}. {skill}")

运行结果:

1. Python
2. SQL
3. Linux

实际使用场景:

示例:打印菜单。

menus = ("查看余额", "转账", "退出")

for number, menu in enumerate(menus, start=1):
    print(f"{number}. {menu}")

运行结果:

1. 查看余额
2. 转账
3. 退出

新手避坑:

skills = ("Python", "SQL")

print(list(enumerate(skills)))

运行结果:

[(0, 'Python'), (1, 'SQL')]

19. 元组不可变的实际优势

元组不可变,不只是限制,也是优势。

19.1 防止数据被误改

config = ("localhost", 3306, "root")

print(config)

运行结果:

('localhost', 3306, 'root')

如果有人想直接改:

config = ("localhost", 3306, "root")

config[1] = 3307

运行结果:

TypeError: 'tuple' object does not support item assignment

实际使用场景:

19.2 表达“只读数据”的意图

roles = ("admin", "editor", "guest")

for role in roles:
    print(role)

运行结果:

admin
editor
guest

看到元组,别人就知道这组角色一般不应该被随便改。

实际使用场景:

新手避坑:

data = ("小王", ["Python", "SQL"])

data[1].append("Linux")

print(data)

运行结果:

('小王', ['Python', 'SQL', 'Linux'])

这点很容易误解。元组不允许你把 data[1] 换成别的对象,但 data[1] 这个列表自身可以修改。

20. 元组作为字典键

字典的键要求是可哈希的,简单理解就是:这个键本身不能随便变。

元组如果里面的元素也都是不可变数据,就可以作为字典键。

locations = {
    (0, 0): "起点",
    (10, 20): "商店",
    (30, 40): "医院"
}

print(locations[(10, 20)])

运行结果:

商店

实际使用场景:

示例:用姓名和城市作为组合键。

users = {
    ("小王", "北京"): "后端开发",
    ("小李", "上海"): "数据分析"
}

print(users[("小王", "北京")])

运行结果:

后端开发

新手避坑:

bad_key = ("小王", ["Python", "SQL"])

data = {
    bad_key: "测试"
}

运行结果:

TypeError: unhashable type: 'list'

因为列表是可变的,放进元组后,整个元组也不能安全地作为字典键。

21. 函数返回多值:本质就是元组

Python 函数可以返回多个值。

def get_user():
    return "小王", 18, "Python"

result = get_user()

print(result)
print(type(result))

运行结果:

('小王', 18, 'Python')
<class 'tuple'>

函数看起来返回了 3 个值,本质上是返回了一个元组。

通常我们会直接解包:

def get_user():
    return "小王", 18, "Python"

name, age, skill = get_user()

print(name)
print(age)
print(skill)

运行结果:

小王
18
Python

实际使用场景:

示例:

def analyze_scores(scores):
    total = sum(scores)
    average = total / len(scores)
    return total, average

total_score, average_score = analyze_scores((90, 80, 70))

print(total_score)
print(average_score)

运行结果:

240
80.0

新手避坑:

def analyze_scores(scores):
    total = sum(scores)
    average = total / len(scores)
    return total, average

_, average_score = analyze_scores((90, 80, 70))

print(average_score)

运行结果:

80.0

22. 函数参数打包:*args

函数定义里写 *args,可以接收不确定数量的位置参数。

这些参数会被打包成一个元组。

def show_numbers(*args):
    print(args)
    print(type(args))

show_numbers(10, 20, 30)

运行结果:

(10, 20, 30)
<class 'tuple'>

实际使用场景:

示例:自定义求和。

def my_sum(*numbers):
    total = 0
    for number in numbers:
        total += number
    return total

print(my_sum(1, 2, 3))
print(my_sum(10, 20, 30, 40))

运行结果:

6
100

新手避坑:

23. 函数参数解包:把元组拆开传进去

如果函数需要多个参数,而你手里有一个元组,可以用 * 把元组拆开传进去。

def introduce(name, age, skill):
    print(f"我叫{name},今年{age}岁,会{skill}")

user = ("小王", 18, "Python")

introduce(*user)

运行结果:

我叫小王,今年18岁,会Python

如果不用 *,会把整个元组当成第一个参数,参数数量就不对。

def introduce(name, age, skill):
    print(name, age, skill)

user = ("小王", 18, "Python")

introduce(user)

运行结果:

TypeError: introduce() missing 2 required positional arguments: 'age' and 'skill'

实际使用场景:

新手避坑:

24. len():获取元组长度

len() 可以获取元组里有多少个元素。

skills = ("Python", "SQL", "Linux")

print(len(skills))

运行结果:

3

实际使用场景:

示例:

user = ("小王", 18, "Python")

if len(user) == 3:
    print("用户信息完整")
else:
    print("用户信息不完整")

运行结果:

用户信息完整

新手避坑:

data = ("小王", (90, 80, 70))

print(len(data))

运行结果:

2

25. max()、min():获取最大值和最小值

元组里如果都是可比较的数据,可以用 max()min()

scores = (90, 85, 100, 60)

print(max(scores))
print(min(scores))

运行结果:

100
60

实际使用场景:

示例:

prices = (199, 299, 99, 399)

print(f"最高价格:{max(prices)}")
print(f"最低价格:{min(prices)}")

运行结果:

最高价格:399
最低价格:99

新手避坑:

data = (100, "200", 300)

print(max(data))

运行结果:

TypeError: '>' not supported between instances of 'str' and 'int'

26. sum():对数字元组求和

sum() 可以对数字元组求和。

scores = (90, 85, 100)

total = sum(scores)

print(total)

运行结果:

275

实际使用场景:

示例:计算平均分。

scores = (90, 85, 100)

total = sum(scores)
average = total / len(scores)

print(total)
print(average)

运行结果:

275
91.66666666666667

新手避坑:

data = ("Python", "SQL")

print(sum(data))

运行结果:

TypeError: unsupported operand type(s) for +: 'int' and 'str'

字符串拼接不要用 sum(),可以用 join()

data = ("Python", "SQL")

print(" + ".join(data))

运行结果:

Python + SQL

27. count():统计某个元素出现次数

count() 用来统计某个值在元组里出现了几次。

levels = ("初级", "中级", "初级", "高级", "初级")

print(levels.count("初级"))
print(levels.count("高级"))

运行结果:

3
1

实际使用场景:

示例:

statuses = ("成功", "失败", "成功", "处理中", "成功")

success_count = statuses.count("成功")

print(f"成功次数:{success_count}")

运行结果:

成功次数:3

新手避坑:

words = ("Python", "python", "PYTHON")

print(words.count("Python"))

运行结果:

1

大小写不同,结果就不同。

28. index():查找元素位置

index() 可以查找某个元素第一次出现的位置。

skills = ("Python", "SQL", "Linux", "Python")

print(skills.index("Python"))
print(skills.index("Linux"))

运行结果:

0
2

注意:index() 返回的是第一次出现的位置。

实际使用场景:

示例:

menus = ("首页", "课程", "订单", "我的")

position = menus.index("订单")

print(position)

运行结果:

2

新手避坑:

menus = ("首页", "课程", "订单", "我的")

print(menus.index("设置"))

运行结果:

ValueError: tuple.index(x): x not in tuple

更安全的写法:

menus = ("首页", "课程", "订单", "我的")

target = "设置"

if target in menus:
    print(menus.index(target))
else:
    print("没有找到")

运行结果:

没有找到

29. 什么时候必须用元组?

严格来说,很多时候列表和元组都能完成任务。但下面几种情况,元组更合适,甚至必须用。

29.1 想作为字典键

point_names = {
    (0, 0): "原点",
    (1, 2): "目标点"
}

print(point_names[(1, 2)])

运行结果:

目标点

列表不能作为字典键:

point_names = {
    [0, 0]: "原点"
}

运行结果:

TypeError: unhashable type: 'list'

29.2 想表达数据不应该被修改

database_config = ("127.0.0.1", 3306, "root")

print(database_config)

运行结果:

('127.0.0.1', 3306, 'root')

配置数据通常不希望运行过程中随便被改,元组更能表达这个意思。

29.3 函数返回多个值

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

small, big = get_range_info((8, 3, 10, 1))

print(small)
print(big)

运行结果:

1
10

Python 返回多个值时,本质就是元组。

29.4 固定结构的数据

rgb = (255, 128, 0)

red, green, blue = rgb

print(red)
print(green)
print(blue)

运行结果:

255
128
0

RGB 颜色值固定就是 3 个数字,用元组非常合适。

30. 新手高频易错点总结

30.1 单元素元组忘记逗号

wrong = ("Python")
right = ("Python",)

print(type(wrong))
print(type(right))

运行结果:

<class 'str'>
<class 'tuple'>

30.2 以为元组绝对不能变

data = ("小王", ["Python"])

data[1].append("SQL")

print(data)

运行结果:

('小王', ['Python', 'SQL'])

元组位置不能改,但里面的可变对象自己还能改。

30.3 解包数量不匹配

info = ("小王", 18, "Python")

name, age = info

运行结果:

ValueError: too many values to unpack (expected 2)

解决办法是变量数量匹配,或者使用 * 接收多余值。

info = ("小王", 18, "Python")

name, *others = info

print(name)
print(others)

运行结果:

小王
[18, 'Python']

30.4 index() 查不到元素会报错

skills = ("Python", "SQL")

target = "Java"

if target in skills:
    print(skills.index(target))
else:
    print("没有这个技能")

运行结果:

没有这个技能

30.5 把元组当列表频繁修改

如果你写代码时总是这样:

data = ("A", "B", "C")

data_list = list(data)
data_list.append("D")
data = tuple(data_list)

print(data)

运行结果:

('A', 'B', 'C', 'D')

说明你可能一开始就应该用列表。

31. 元组实战:封装用户数据并批量处理

最后用一个接近实际开发的小例子,把元组、解包、zip()enumerate() 串起来。

# 用户字段和用户数据
fields = ("name", "age", "skill")
users = (
    ("小王", 18, "Python"),
    ("小李", 20, "SQL"),
    ("小张", 22, "Linux")
)

for index, user in enumerate(users, start=1):
    # zip 把字段名和值配对,再转成字典
    user_dict = dict(zip(fields, user))

    print(f"第 {index} 个用户")
    print(user_dict)

运行结果:

第 1 个用户
{'name': '小王', 'age': 18, 'skill': 'Python'}
第 2 个用户
{'name': '小李', 'age': 20, 'skill': 'SQL'}
第 3 个用户
{'name': '小张', 'age': 22, 'skill': 'Linux'}

这个例子里:

实际使用场景:

32. 知识点总结

这篇文章讲了 Python 元组的基础和高级用法,新手重点记住下面这些:

  1. 元组用来保存一组固定数据,创建后不能直接修改元素。
  2. 单元素元组必须写逗号,比如 ("Python",)
  3. 元组可以解包,比如 name, age = ("小王", 18)
  4. 星号 * 可以做不定长解包,比如 first, *rest = data
  5. 元组可以嵌套,适合保存简单的结构化数据。
  6. 元组可以和列表、字典、集合互相转换,但要注意转换后的数据特性。
  7. 元组可以拼接和重复,但都会生成新元组,不会修改原元组。
  8. zip() 常用于批量配对数据,返回的是一组组元组。
  9. enumerate() 常用于遍历元组时同时拿序号和值
  10. 元组不可变能防止误改,适合配置常量、固定选项、只读数据。
  11. 元组可以作为字典键,前提是里面的元素也都不可变。
  12. 函数返回多个值,本质上就是返回元组
  13. 函数里的 *args 会把多个参数打包成元组
  14. 调用函数时 *tuple 可以把元组拆开传参
  15. 常用函数和方法包括 len()max()min()sum()count()index()

最后再用一句话收尾:

如果数据后面要改,用列表;如果数据固定、不希望被误改、要作为组合键或函数返回多个值,用元组。

把这个判断记住,Python 元组就不难了。

以上就是Python元组(Tuple)全部高级用法大全的详细内容,更多关于Python元组(Tuple)高级用法的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文