卡码笔记-最强八股文
首页
计算机基础
Python
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
大模型Github (opens new window)
代码随想录 (opens new window)
首页
计算机基础
Python
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
大模型Github (opens new window)
代码随想录 (opens new window)
  • 本栏必读

    • Python面试题专栏介绍
    • Python学习路线
    • Python零基础入门课
  • 基础语法

    • Python有哪些内置数据类型?
    • Python变量保存的是什么?
    • 可变对象和不可变对象有什么区别?
    • is和==有什么区别?
    • Python的运算符有哪些?
    • Python条件判断和循环的常见写法与易错点
    • Python字符串为什么不可变?
    • Python列表和元组有什么区别?
    • Python字典和集合有什么区别?
    • Python切片和序列解包怎么用?
      • 简要回答
      • 详细回答
      • 知识拓展
    • 列表、字典和集合推导式怎么写?
  • 函数、作用域与模块

  • 面向对象

  • 进阶语法与语言机制

# Python切片和序列解包怎么用?

面试官问:“Python切片和序列解包分别是什么?有哪些常见用法和易错点?”

很多人能写出nums[1:3]和a, b = [1, 2],但对负索引、步长、切片拷贝行为、星号解包和嵌套解包容易答不清楚。这道题要讲清楚的是切片和解包各自的语法边界、典型场景以及对象修改的影响。

# 简要回答

切片(slice)用于从序列中提取子序列,语法是seq[start:stop:step],返回新序列。支持负索引(从末尾倒数)、省略边界、反向步长等灵活写法。切片返回的是浅拷贝,修改子序列不影响原序列,但嵌套的可变对象仍然共享。

序列解包(unpacking)用于把序列元素一次性赋给多个变量,最常见的是a, b = [1, 2]。Python 3支持星号表达式*rest收集剩余元素,也支持嵌套解包。解包要求左右两侧元素数量匹配(除非用了星号),否则抛出ValueError。

两者都适用于列表、元组、字符串等序列类型。解包实际上只要求右侧是可迭代对象,所以集合、字典、生成器也能解包。

# 详细回答

# 切片基础语法

切片用三个参数指定范围:[start:stop:step]。

  • start:起始位置(包含),默认0。
  • stop:结束位置(不包含),默认序列末尾。
  • step:步长,默认1。
nums = [0, 1, 2, 3, 4, 5]
print(nums[1:4])     # [1, 2, 3]
print(nums[:3])      # [0, 1, 2] 从头开始
print(nums[3:])      # [3, 4, 5] 到末尾
print(nums[::2])     # [0, 2, 4] 每隔一个
print(nums[::-1])    # [5, 4, 3, 2, 1, 0] 反转
1
2
3
4
5
6

负索引从末尾倒数,-1表示最后一个元素:

print(nums[-3:])     # [3, 4, 5] 最后三个
print(nums[:-2])     # [0, 1, 2, 3] 去掉最后两个
print(nums[-4:-1])   # [2, 3, 4]
1
2
3

切片索引与负索引对应关系

图中展示了正索引从0开始向右递增,负索引从-1(最后一个元素)开始向左递减,两者可以定位到同一个元素。

# 切片是浅拷贝

切片返回新对象,修改切片结果不影响原列表:

original = [1, 2, 3, 4]
sub = original[1:3]
sub[0] = 99
print(original)  # [1, 2, 3, 4] 不变
print(sub)       # [99, 3]
1
2
3
4
5

但如果列表内嵌套可变对象,拷贝的是引用:

matrix = [[1, 2], [3, 4]]
sub = matrix[0:1]
sub[0][0] = 99
print(matrix)  # [[99, 2], [3, 4]] 原列表也变了
1
2
3
4

切片只复制了外层列表,里面的[1, 2]仍然是同一个对象。可变对象被原地修改,所有指向它的地方都能看到变化,原理见《Python中的可变对象和不可变对象有什么区别?》。

# 切片赋值

切片赋值会原地修改列表,长度可以和原切片不一样:

nums = [0, 1, 2, 3, 4]
nums[1:3] = [10, 20, 30]  # 可以不等长
print(nums)  # [0, 10, 20, 30, 3, 4]

nums[1:4] = []  # 删除元素
print(nums)  # [0, 3, 4]
1
2
3
4
5
6

给切片赋空列表等价于del nums[1:4]。元组和字符串不可变,不支持切片赋值,列表和元组的这类差异见《Python列表和元组有什么区别?》。

# 序列解包基础

最简单的解包是一一对应:

point = (3, 4)
x, y = point
print(x, y)  # 3 4

name, age = ["Alice", 25]
print(name, age)  # Alice 25
1
2
3
4
5
6

左右元素数量必须匹配:

try:
    a, b = [1, 2, 3]
except ValueError as e:
    print(e)  # too many values to unpack (expected 2)
1
2
3
4

# 星号表达式收集剩余元素

Python 3支持用*变量收集多余元素:

first, *rest = [1, 2, 3, 4]
print(first)  # 1
print(rest)   # [2, 3, 4]

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

a, *middle, b = [1, 2, 3, 4, 5]
print(middle)  # [2, 3, 4]
1
2
3
4
5
6
7
8
9
10

星号变量收集的始终是列表,即使只有一个元素或为空:

a, *b = [1]
print(b)  # []

*x, y, z = [1, 2]
print(x)  # []
1
2
3
4
5

序列解包与星号表达式

图中展示了普通解包要求数量严格匹配,星号表达式可以收集剩余元素到一个列表中,位置灵活。

# 嵌套解包

解包可以嵌套,常用于多维数据:

point = (1, (2, 3))
x, (y, z) = point
print(x, y, z)  # 1 2 3

users = [("Alice", 25), ("Bob", 30)]
for name, age in users:
    print(name, age)
1
2
3
4
5
6
7

结构必须匹配,否则报错:

try:
    a, (b, c) = [1, [2]]
except ValueError as e:
    print(e)  # not enough values to unpack (expected 2, got 1)
1
2
3
4

# 字符串也支持切片和解包

字符串是不可变序列,切片返回新字符串,背后原因见《Python字符串为什么不可变?常用操作有哪些?》:

s = "Python"
print(s[1:4])    # yth
print(s[::-1])   # nohtyP

first, *rest = s
print(first)  # P
print(rest)   # ['y', 't', 'h', 'o', 'n']
1
2
3
4
5
6
7

注意解包字符串时,每个字符作为一个元素。

# 知识拓展

面试官可能追问:

Q1:切片索引越界会报错吗?

不会。切片索引超出范围时,Python自动调整到有效范围:

nums = [1, 2, 3]
print(nums[10:20])  # []
print(nums[-10:2])  # [1, 2]
1
2
3

这和直接访问nums[10]会抛出IndexError不同。

Q2:如何复制整个列表?

nums[:]和nums.copy()都是浅拷贝:

original = [1, 2, 3]
copy1 = original[:]
copy2 = original.copy()
1
2
3

两者效果相同。需要深拷贝嵌套结构时,用copy.deepcopy()。

Q3:可以一次解包多个序列吗?

可以用zip()配合解包:

names = ["Alice", "Bob"]
ages = [25, 30]
for name, age in zip(names, ages):
    print(name, age)
1
2
3
4

Q4:解包时可以忽略某些元素吗?

约定用_接收不需要的元素:

_, y, _ = [1, 2, 3]
print(y)  # 2

first, *_ = [1, 2, 3, 4]  # 只要第一个
1
2
3
4

_是普通变量名,只是约定俗成表示“忽略”。

Q5:字典可以解包吗?

字典解包时,默认迭代的是键:

d = {"a": 1, "b": 2}
x, y = d
print(x, y)  # a b

# 要解包键值对,用 .items()
for k, v in d.items():
    print(k, v)
1
2
3
4
5
6
7

函数调用时用**把字典展开成关键字参数,属于函数参数的话题,和这里的赋值解包不是一回事。

Last Updated: 10/13/2026, 5:57:00 PM

← Python字典和集合有什么区别? 列表、字典和集合推导式怎么写? →

评论

验证登录状态...

侧边栏 侧边栏
夜间模式 夜间
卡码简历 卡码简历
代码随想录 代码随想录
卡码投递表 卡码投递表🔥
2026实习校招群 2026群
添加客服微信 2026实习校招客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记 支持卡码笔记
鼓励/支持/赞赏Carl 卡码笔记赞赏码
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪