切片
切片就像切蛋糕,可以获取列表的一部分。基本语法:
列表[开始:结束:步长]
python
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print("原始列表:", numbers)
# 基本切片
print("\n=== 基本切片 ===")
print(f"numbers[2:6] = {numbers[2:6]}") # 索引2到6(不包括6)
print(f"numbers[:4] = {numbers[:4]}") # 从开始到索引4
print(f"numbers[5:] = {numbers[5:]}") # 从索引5到结束
print(f"numbers[:] = {numbers[:]}") # 整个列表的副本
切片参数详解:
| 参数 | 含义 | 默认值 | 示例 |
|---|---|---|---|
start |
开始位置(包含) | 0 | [2:] 从索引2开始 |
stop |
结束位置(不包含) | 列表长度 | [:5] 到索引5结束 |
step |
步长(每隔几个取一个) | 1 | [::2] 每隔一个取一个 |
各种切片操作详解
基本切片操作
python
letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
print("原始列表:", letters)
# 获取连续的子列表
print("\n=== 连续切片 ===")
print(f"letters[1:4] = {letters[1:4]}") # ['B', 'C', 'D'] - 索引1到4
print(f"letters[:3] = {letters[:3]}") # ['A', 'B', 'C'] - 前3个元素
print(f"letters[3:] = {letters[3:]}") # ['D', 'E', 'F', 'G'] - 从索引3开始
print(f"letters[2:5] = {letters[2:5]}") # ['C', 'D', 'E'] - 索引2到5
# 使用负索引切片
print("\n=== 负索引切片 ===")
print(f"letters[-4:] = {letters[-4:]}") # ['D', 'E', 'F', 'G'] - 最后4个
print(f"letters[:-2] = {letters[:-2]}") # ['A', 'B', 'C', 'D', 'E'] - 除了最后2个
print(f"letters[-5:-2] = {letters[-5:-2]}") # ['C', 'D', 'E'] - 倒数第5到倒数第2
带步长的切片
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print("原始列表:", numbers)
print("\n=== 步长切片 ===")
print(f"numbers[::2] = {numbers[::2]}") # [0, 2, 4, 6, 8] - 每隔一个取一个
print(f"numbers[1::2] = {numbers[1::2]}") # [1, 3, 5, 7, 9] - 从索引1开始,每隔一个
print(f"numbers[::3] = {numbers[::3]}") # [0, 3, 6, 9] - 每隔两个取一个
print(f"numbers[2:8:2] = {numbers[2:8:2]}") # [2, 4, 6] - 索引2到8,每隔一个
负步长切片(反转)
numbers = [0, 1, 2, 3, 4, 5]
print("原始列表:", numbers)
print("\n=== 负步长切片 ===")
print(f"numbers[::-1] = {numbers[::-1]}") # [5, 4, 3, 2, 1, 0] - 反转列表
print(f"numbers[::-2] = {numbers[::-2]}") # [5, 3, 1] - 反转后每隔一个
print(f"numbers[4:1:-1] = {numbers[4:1:-1]}") # [4, 3, 2] - 从索引4到索引1,反向
print(f"numbers[5:0:-2] = {numbers[5:0:-2]}") # [5, 3, 1] - 从索引5到索引0,反向每隔一个
切片的实用技巧
列表复制
original = [1, 2, 3, 4, 5]
# 创建列表的副本(重要!)
copy1 = original[:] # 方法1:使用切片
copy2 = original.copy() # 方法2:使用copy()方法
print(f"原始列表: {original}")
print(f"切片副本: {copy1}")
print(f"copy()副本: {copy2}")
# 修改副本不会影响原列表
copy1[0] = 100
print(f"\n修改副本后:")
print(f"原始列表: {original}") # [1, 2, 3, 4, 5] - 不变
print(f"切片副本: {copy1}") # [100, 2, 3, 4, 5] - 已修改
# 错误做法:直接赋值(不是复制)
wrong_copy = original
wrong_copy[0] = 999
print(f"\n直接赋值后:")
print(f"原始列表: {original}") # [999, 2, 3, 4, 5] - 也被修改了!
print(f"错误副本: {wrong_copy}") # [999, 2, 3, 4, 5]
列表反转
numbers = [1, 2, 3, 4, 5]
print("原始列表:", numbers)
# 三种反转方法
reversed1 = numbers[::-1] # 方法1:切片(创建新列表)
reversed2 = list(reversed(numbers)) # 方法2:reversed()函数
numbers.reverse() # 方法3:原地反转(修改原列表)
print(f"切片反转: {reversed1}") # [5, 4, 3, 2, 1]
print(f"reversed(): {reversed2}") # [5, 4, 3, 2, 1]
print(f"原地反转后原列表: {numbers}") # [5, 4, 3, 2, 1]
提取特定元素
data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
print("原始数据:", data)
# 提取奇数位置元素(索引1,3,5...)
odd_positions = data[1::2]
print(f"奇数位置元素: {odd_positions}") # [20, 40, 60, 80, 100]
# 提取偶数位置元素(索引0,2,4...)
even_positions = data[::2]
print(f"偶数位置元素: {even_positions}") # [10, 30, 50, 70, 90]
# 提取前三分之一、中间三分之一、后三分之一
length = len(data)
first_third = data[:length//3]
middle_third = data[length//3:2*length//3]
last_third = data[2*length//3:]
print(f"前三分之一: {first_third}") # [10, 20, 30]
print(f"中间三分之一: {middle_third}") # [40, 50, 60]
print(f"后三分之一: {last_third}") # [70, 80, 90, 100]
切片的高级应用
切片赋值(修改列表)
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print("原始列表:", numbers)
# 替换切片范围的元素
numbers[2:5] = [20, 30, 40] # 替换索引2-5的元素
print(f"替换后: {numbers}") # [0, 1, 20, 30, 40, 5, 6, 7, 8, 9]
# 插入元素(不删除,只插入)
numbers[3:3] = [25, 26] # 在索引3的位置插入
print(f"插入后: {numbers}") # [0, 1, 20, 25, 26, 30, 40, 5, 6, 7, 8, 9]
# 删除元素(用空列表替换)
numbers[5:7] = [] # 删除索引5-7的元素
print(f"删除后: {numbers}") # [0, 1, 20, 25, 26, 5, 6, 7, 8, 9]
# 扩展列表
numbers[len(numbers):] = [100, 200] # 在末尾添加元素
print(f"扩展后: {numbers}") # [0, 1, 20, 25, 26, 5, 6, 7, 8, 9, 100, 200]
多维列表切片
# 二维列表(矩阵)
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
]
print("原始矩阵:")
for row in matrix:
print(row)
# 提取子矩阵
print("\n=== 子矩阵提取 ===")
sub_matrix = matrix[1:3] # 第2-3行
print("第2-3行:")
for row in sub_matrix:
print(row)
# 提取特定列(需要遍历)
second_column = [row[1] for row in matrix] # 每行的第2个元素
print(f"\n第2列: {second_column}") # [2, 6, 10, 14]
# 提取子矩阵的特定区域
top_left = [row[:2] for row in matrix[:2]] # 前2行的前2列
print("\n左上角2x2子矩阵:")
for row in top_left:
print(row)
字符串切片(同样适用)
text = "Hello, Python World!"
print("原始字符串:", text)
# 字符串切片与列表切片语法相同
print(f"前5个字符: '{text[:5]}'") # 'Hello'
print(f"第7到13个字符: '{text[7:13]}'") # 'Python'
print(f"每隔一个字符: '{text[::2]}'") # 'Hlo yhnWrd'
print(f"反转字符串: '{text[::-1]}'") # '!dlroW nohtyP ,olleH'
# 提取单词
words = text.split() # 先分割成单词列表
print(f"\n单词列表: {words}")
print(f"第一个单词: '{words[0]}'") # 'Hello,'
print(f"最后一个单词: '{words[-1]}'") # 'World!'
常见错误和注意事项
索引越界错误
fruits = ["苹果", "香蕉", "橙子"]
# 正确的索引范围:0 到 2(或 -1 到 -3)
print(fruits[0]) # ✅ 正确
print(fruits[-1]) # ✅ 正确
# 索引越界会报错
# print(fruits[5]) # ❌ 错误:IndexError
# print(fruits[-5]) # ❌ 错误:IndexError
# 但切片不会越界错误!
print(fruits[1:10]) # ✅ 正确:['香蕉', '橙子'] - 自动截断到列表末尾
print(fruits[-10:2]) # ✅ 正确:['苹果', '香蕉'] - 自动从开始处理
切片边界理解
numbers = [0, 1, 2, 3, 4, 5]
print("理解切片边界:")
print(f"numbers[1:4] = {numbers[1:4]}") # [1, 2, 3] - 包含开始,不包含结束
print(f"numbers[0:3] = {numbers[0:3]}") # [0, 1, 2] - 索引3的元素不包含
print(f"numbers[3:3] = {numbers[3:3]}") # [] - 开始等于结束,得到空列表
# 记住口诀:"含头不含尾"
步长为0的错误
numbers = [1, 2, 3, 4, 5]
# 步长不能为0
# print(numbers[::0]) # ❌ 错误:ValueError: slice step cannot be zero
# 正确的步长应该是非零整数
print(numbers[::1]) # ✅ 正确:正常顺序
print(numbers[::2]) # ✅ 正确:每隔一个
print(numbers[::-1]) # ✅ 正确:反转
实战练习
练习1:数据处理
# 假设有一组温度数据
temperatures = [22.5, 23.1, 24.8, 25.3, 26.7, 27.2, 28.9, 29.4, 30.1, 31.5]
print("温度数据:", temperatures)
# 提取工作日温度(假设前5个是工作日)
weekday_temps = temperatures[:5]
print(f"工作日温度: {weekday_temps}")
# 提取周末温度(后2个是周末)
weekend_temps = temperatures[-2:]
print(f"周末温度: {weekend_temps}")
# 计算平均温度
average_temp = sum(temperatures) / len(temperatures)
print(f"平均温度: {average_temp:.2f}°C")
# 找出最高和最低温度
max_temp = max(temperatures)
min_temp = min(temperatures)
print(f"最高温度: {max_temp}°C, 最低温度: {min_temp}°C")
练习2:文本处理
def process_text(text, max_length=50):
"""处理文本,确保不超过指定长度"""
if len(text) <= max_length:
return text
# 如果太长,截断并添加省略号
truncated = text[:max_length-3] + "..."
return truncated
# 测试
long_text = "这是一个非常长的文本,需要被截断以适合显示在有限的屏幕空间内。"
short_text = "短文本"
print(process_text(long_text)) # 这是一个非常长的文本,需要被截断以适合显示在...
print(process_text(short_text)) # 短文本
练习3:分页功能
def paginate(items, page_size, page_number):
"""实现简单的分页功能"""
start_index = (page_number - 1) * page_size
end_index = start_index + page_size
page_items = items[start_index:end_index]
total_pages = (len(items) + page_size - 1) // page_size
return {
'items': page_items,
'current_page': page_number,
'total_pages': total_pages,
'has_next': page_number < total_pages,
'has_prev': page_number > 1
}
# 测试分页
all_items = list(range(1, 26)) # 1到25的数字
page_size = 5
for page in range(1, 6):
result = paginate(all_items, page_size, page)
print(f"第{page}页: {result['items']}, 总页数: {result['total_pages']}")
总结
切片的核心要点
-
语法 :
list[start:stop:step] -
边界:包含start,不包含stop
-
默认值:start默认为0,stop默认为列表长度,step默认为1
-
负值:负索引从末尾计数,负步长表示反向
-
安全:切片不会引发索引越界错误
实用技巧总结
-
复制列表 :使用
new_list = old_list[:] -
反转列表 :使用
reversed_list = original[::-1] -
提取元素:灵活组合开始、结束、步长参数
-
修改列表:通过切片赋值来替换、插入、删除元素