课程 22:元组与排序
1. 元组基础与进阶
1.1 什么是元组?
元组(tuple)是不可变的有序序列,用小括号 () 表示。元素类型不限,支持嵌套。
与列表区别: 元组不可变,适合存储只读数据,可作为字典键和集合元素。
1.2 元组的定义与访问
# 定义元组
t = (1, 2, 3)
print(t[0])
# 单元素元组
t1 = (5,)
# 嵌套元组
t2 = (1, (2, 3), 4)
print(t2[1][0])
常用操作:
• 访问元素:t[i]
• 切片:t[1:3]
• 遍历:for x in t
1.3 元组的解包与多返回值
# 多变量赋值
x, y, z = (1, 2, 3)
# 星号解包
head, *body, tail = (1, 2, 3, 4, 5)
print(head, body, tail) # 1 [2, 3, 4] 5
# 函数多返回值
def min_max(lst):
return min(lst), max(lst)
lo, hi = min_max([3, 1, 4])
print(lo, hi)
解包可用于交换变量、函数参数、循环遍历等。
1.4 namedtuple与类型注解
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(3, 4)
print(p.x, p.y)
# 类型注解
from typing import Tuple
point: Tuple[int, int] = (3, 4)
namedtuple适合结构化只读数据,类型注解提升代码可读性和静态检查。
1.5 元组的hash特性与不可变性安全
t = (1, 2, 3)
print(hash(t))
# 元组可作为dict的key,list不行
d = {(1,2): 'a'}
print(d[(1,2)])
# t[0] = 10 # TypeError
元组元素必须全为可hash类型,才能作为字典键或集合元素。
1.6 元组与list互转、内存与性能
lst = [1,2,3]
t = tuple(lst)
lst2 = list(t)
import sys
print(sys.getsizeof(lst), sys.getsizeof(t))
元组通常比列表更省内存,且不可变更安全。
1.7 tuple vs list vs set vs dict
| 特性 |
tuple |
list |
set |
dict |
| 可变性 |
不可变 |
可变 |
可变 |
可变 |
| 有序性 |
有序 |
有序 |
无序 |
3.7+有序 |
| 可哈希 |
是 |
否 |
否 |
否 |
| 用途 |
只读/键 |
通用 |
去重 |
映射 |
tuple适合不可变、只读、作为key,list适合频繁增删改,set适合去重,dict适合映射。
2. 元组的不可变性与应用
2.1 不可变性
t = (1, 2, 3)
# t[0] = 10 # TypeError: 'tuple' object does not support item assignment
注意: 元组本身不可变,但如果元素是可变对象(如列表),其内容可变。
t = ([1,2], 3)
t[0][0] = 99
print(t) # ([99, 2], 3)
3. 排序详解与算法原理
3.1 sorted与sort
nums = [3, 1, 4, 1, 5]
print(sorted(nums)) # 返回新列表
nums.sort(reverse=True)
print(nums) # 原地排序
Python排序算法为Timsort,稳定且高效,复杂度O(n log n)。
3.2 key参数与自定义排序
words = ['apple', 'banana', 'pear', 'grape']
print(sorted(words, key=len)) # 按长度排序
# 排序元组列表
students = [('Alice', 95), ('Bob', 88), ('Tom', 90)]
print(sorted(students, key=lambda x: x[1], reverse=True))
常用技巧:
• key参数指定排序依据
• reverse=True降序排序
• 支持任意可迭代对象
3.3 operator模块与itemgetter
from operator import itemgetter
students = [('Alice', 95), ('Bob', 88), ('Tom', 90)]
print(sorted(students, key=itemgetter(1), reverse=True))
itemgetter比lambda更快,适合大数据量排序。
3.4 多级排序与分组聚合
# 按成绩降序,成绩相同按姓名升序
students = [('Alice', 95), ('Bob', 88), ('Tom', 95)]
result = sorted(students, key=lambda x: (-x[1], x[0]))
print(result)
# 分组聚合
grouped = {}
for name, score in students:
grouped.setdefault(score, []).append(name)
print(grouped)
分组统计常用于数据分析,groupby需先排序。
3.5 排序性能分析与大数据处理
import random, time
lst = [random.randint(0, 100000) for _ in range(10**6)]
start = time.time()
sorted(lst)
print('耗时:', time.time()-start)
大数据排序建议用numpy、pandas等库,或分块处理。
4. 实际应用案例与可视化
4.1 元组作为字典键
d = {('Alice', 'Math'): 95, ('Bob', 'Math'): 88}
print(d[('Alice', 'Math')])
4.2 数据分析与可视化
import matplotlib.pyplot as plt
scores = [('Alice', 95), ('Bob', 88), ('Tom', 90)]
names = [x[0] for x in scores]
values = [x[1] for x in scores]
plt.bar(names, values)
plt.show()
元组常用于pandas、numpy等数据分析库的数据结构。
4.3 真实项目案例
# 经纬度坐标存储与排序
gps_points = [(39.9, 116.4), (31.2, 121.5), (22.5, 114.1)]
gps_points.sort(key=lambda x: x[0])
# 复杂数据分组与排名
from collections import defaultdict
scores = [('Alice', 'A', 95), ('Bob', 'B', 88), ('Tom', 'A', 90)]
grouped = defaultdict(list)
for name, cls, score in scores:
grouped[cls].append((name, score))
for cls, items in grouped.items():
print(cls, sorted(items, key=lambda x: -x[1]))
项目实战:用元组和排序实现学生成绩分析、地理信息管理、日志分析等。