列表、元组与切片
通过经典编程题中的实践示例,掌握 Python 列表操作、切片语法和元组不可变性。
列表、元组与切片 是 CoddyKit 上的免费 DSA Interview Prep 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 DSA Interview Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 DSA Interview Prep 课程共包含 4 节课。
Python 列表:动态数组
Python 的列表是一种可以存放任意内容并自动扩展的动态数组。它有序且可变,还能通过索引即时进行 O(1) 访问。代码展示了基本用法。
nums = [3, 1, 4, 1, 5]
print(nums[0]) # 3
print(nums[-1]) # 5 (last element)
nums.append(9)
print(len(nums)) # 6常见的列表操作
请牢记这些操作:在末尾使用 append 和 pop 的复杂度是 O(1),但在开头使用 insert 的复杂度是 O(n)。请避免在紧密循环中使用 remove,因为它每次都会重新扫描列表。
stack = []
stack.append(1)
stack.append(2)
stack.append(3)
print(stack.pop()) # 3 O(1)
print(stack) # [1, 2]
# insert at index 0 is O(n)
stack.insert(0, 0)
print(stack) # [0, 1, 2]切片语法详解
切片的写法是 lst[start:stop:step],并且会在 stop 之前停止。一个经典技巧是:步长为 -1 可以在不改变原列表的情况下将列表反转。代码会逐一演示每种写法。
a = [0, 1, 2, 3, 4, 5]
print(a[1:4]) # [1, 2, 3]
print(a[:3]) # [0, 1, 2]
print(a[3:]) # [3, 4, 5]
print(a[::2]) # [0, 2, 4] every other
print(a[::-1]) # [5, 4, 3, 2, 1, 0] reversed切片会创建浅拷贝
有一个实用但容易踩坑的地方:切片总会创建一个新列表,因此修改切片不会影响原列表。但它是浅拷贝,所以其中的嵌套列表仍然是共享的。请务必注意。
original = [1, 2, 3]
copy = original[:] # shallow copy
copy[0] = 99
print(original) # [1, 2, 3] unchanged
# Nested list pitfall
nested = [[1, 2], [3, 4]]
shallow = nested[:]
shallow[0][0] = 99
print(nested) # [[99, 2], [3, 4]] changed!元组:不可变序列
元组使用圆括号表示,创建后便不能修改。由于元组可哈希,因此可以作为字典键或集合元素,非常适合在网格题中表示 (row, col) 坐标对。
point = (3, 7)
print(point[0]) # 3
# Use as dict key
grid = {}
grid[(0, 0)] = 'start'
grid[(2, 3)] = 'end'
print(grid[(0, 0)]) # start
# Unpacking
x, y = point
print(x, y) # 3 7何时使用元组而非列表
如果数据不应改变,请选择元组;如果数据需要改变,请选择列表。元组占用的内存也略少一些,在 Dijkstra 算法的大型堆中,这种差异会逐渐累积。
import sys
a_list = [1, 2, 3, 4, 5]
a_tuple = (1, 2, 3, 4, 5)
print(sys.getsizeof(a_list)) # e.g. 104 bytes
print(sys.getsizeof(a_tuple)) # e.g. 80 bytes
# Tuple returned from function
def min_max(nums):
return min(nums), max(nums)
lo, hi = min_max([3, 1, 4, 1, 5])
print(lo, hi) # 1 5切片中的差一位错误
差一位错误是数组题中最常见的陷阱。请记住,lst[i:j] 恰好会得到 j-i 个元素。要从中间分割,左半部分是 lst[:mid],右半部分是 lst[mid:]。
lst = [1, 2, 3, 4, 5, 6]
mid = len(lst) // 2 # 3
left = lst[:mid] # [1, 2, 3]
right = lst[mid:] # [4, 5, 6]
print(left, right)
# How many elements?
print(len(lst[2:5])) # 3 (indices 2,3,4)面试中的负索引
Python 支持负索引:lst[-1] 表示最后一个元素,lst[-2] 表示倒数第二个元素。请优先使用 lst[-1],而不是 lst[len(lst)-1];面试官会注意到这种更简洁的写法。
s = 'abcde'
print(s[-1]) # 'e'
print(s[-3:]) # 'cde'
print(s[:-2]) # 'abc' (all except last 2)
nums = [10, 20, 30, 40]
print(nums[-2]) # 30
nums[-1] = 99
print(nums) # [10, 20, 30, 99]列表排序与比较
Python 使用 Timsort 进行排序,复杂度为 O(n log n),并且排序稳定。lst.sort() 会原地修改列表;sorted(lst) 会返回一个新列表。请使用 key 参数实现自定义排序顺序。代码中有示例。
words = ['banana', 'fig', 'apple', 'kiwi']
words.sort(key=len)
print(words) # ['fig', 'kiwi', 'apple', 'banana']
nums = [3, 1, 4, 1, 5]
print(sorted(nums, reverse=True)) # [5, 4, 3, 1, 1]
print(nums) # unchanged: [3, 1, 4, 1, 5]迭代时修改列表
这是一个经典陷阱:循环遍历列表时绝不要添加或删除元素,否则可能跳过元素或导致程序崩溃。请改用列表推导式创建一个新列表。
# WRONG — skips elements
nums = [1, 2, 3, 4, 5]
for n in nums:
if n % 2 == 0:
nums.remove(n) # skips 4!
print(nums) # [1, 3, 5]... but 4 got skipped? Actually removes 2,4
# CORRECT — build new list
nums = [1, 2, 3, 4, 5]
nums = [n for n in nums if n % 2 != 0]
print(nums) # [1, 3, 5]循环中的元组解包
元组解包可以让循环保持简洁:enumerate 会提供 (index, value),而 zip 可以同时遍历两个列表。* 剩余项语法会将尾部内容收集到自己的变量中。请查看代码。
nums = [10, 20, 30]
for i, v in enumerate(nums):
print(i, v)
# 0 10 / 1 20 / 2 30
a = [1, 2, 3]
b = ['x', 'y', 'z']
for x, y in zip(a, b):
print(x, y)
first, *rest = [1, 2, 3, 4]
print(first, rest) # 1 [2, 3, 4]快速测验
快速检查一下,看看您对 Python 列表、元组和切片掌握了多少。您一定可以做到。💪
课程回顾
回顾一下:列表是支持 O(1) append 的动态数组,切片总会返回一个新的副本,而元组不可变且可哈希。接下来我们将学习字典和集合。
常见问题解答
「列表、元组与切片」课时是免费的吗?
是的 — 「列表、元组与切片」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 DSA Interview Prep 课程的其余内容,请升级到 CoddyKit PRO。 DSA Interview Prep 课程共包含 4 节课。
「列表、元组与切片」这节课中我会学到什么?
通过经典编程题中的实践示例,掌握 Python 列表操作、切片语法和元组不可变性。 你通过在浏览器中直接运行的动手代码来练习 DSA Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 DSA Interview Prep 需要有经验吗?
无需任何先前经验。CoddyKit 上的 DSA Interview Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「列表、元组与切片」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 DSA Interview Prep 课中编写并运行代码吗?
能。每节 DSA Interview Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。