Python list花式用法集锦
一、切片的花式玩法
1. 反转列表
lst = [1, 2, 3, 4, 5]
print(lst[::-1]) # [5, 4, 3, 2, 1]
2. 隔一个取一个
lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(lst[::2]) # [0, 2, 4, 6, 8]
print(lst[1::2]) # [1, 3, 5, 7, 9]
3. 用切片赋值实现“原地替换”
lst = [1, 2, 3, 4, 5]
lst[1:4] = [20, 30] # 长度可以变
print(lst) # [1, 20, 30, 5]
4. 用切片删除一段
lst = [1, 2, 3, 4, 5]
del lst[1:4]
print(lst) # [1, 5]
5. 用切片清空但保留引用
lst = [1, 2, 3]
lst[:] = [] # 原地清空,其他引用这个列表的变量也会看到空
print(lst) # []
和 lst = [] 的区别:
a = [1, 2, 3]
b = a
a = [] # a 指向新列表,b 还是 [1, 2, 3]
print(b) # [1, 2, 3]
a = [1, 2, 3]
b = a
a[:] = [] # 原地清空,a 和 b 都变空
print(b) # []
6. 用切片复制
lst = [1, 2, 3]
copy1 = lst[:] # 浅拷贝
copy2 = lst.copy()
copy3 = list(lst)
二、列表推导式的花式玩法
1. 条件表达式(三元)
nums = [1, 2, 3, 4, 5]
result = [x**2 if x % 2 == 0 else -x for x in nums]
print(result) # [-1, 4, -3, 16, -5]
2. 多层嵌套
matrix = [[1, 2], [3, 4], [5, 6]]
flat = [x for row in matrix for x in row]
print(flat) # [1, 2, 3, 4, 5, 6]
3. 多个条件
nums = [x for x in range(30) if x % 2 == 0 if x % 3 == 0]
print(nums) # [0, 6, 12, 18, 24]
4. 生成笛卡尔积
colors = ["红", "绿"]
sizes = ["S", "M", "L"]
combos = [(c, s) for c in colors for s in sizes]
print(combos)
# [('红', 'S'), ('红', 'M'), ('红', 'L'), ('绿', 'S'), ('绿', 'M'), ('绿', 'L')]
5. 转置矩阵
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = [[row[i] for row in matrix] for i in range(3)]
print(transposed) # [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
6. 用 zip(*matrix) 转置
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = [list(row) for row in zip(*matrix)]
print(transposed) # [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
zip(*matrix) 是转置的经典技巧,* 把矩阵解包成多个参数。
7. 条件筛选 + 去重
nums = [1, 1, 2, 2, 3, 3, 4]
unique_evens = list(dict.fromkeys(x for x in nums if x % 2 == 0))
print(unique_evens) # [2, 4]
三、zip 和 enumerate 的花式玩法
1. zip 转字典
keys = ["name", "age", "city"]
values = ["小明", 25, "北京"]
d = dict(zip(keys, values))
print(d) # {'name': '小明', 'age': 25, 'city': '北京'}
2. zip 解压
pairs = [("小明", 25), ("小红", 30), ("小刚", 28)]
names, ages = zip(*pairs)
print(names) # ('小明', '小红', '小刚')
print(ages) # (25, 30, 28)
3. enumerate 配合字典
fruits = ["apple", "banana", "cherry"]
d = {i: fruit for i, fruit in enumerate(fruits)}
print(d) # {0: 'apple', 1: 'banana', 2: 'cherry'}
# 反过来:值作键,索引作值
d = {fruit: i for i, fruit in enumerate(fruits)}
print(d) # {'apple': 0, 'banana': 1, 'cherry': 2}
4. zip 找共同元素
a = [1, 2, 3]
b = [2, 3, 4]
common = [x for x, y in zip(a, b) if x == y]
print(common) # [2, 3]
5. zip 两两配对
lst = [1, 2, 3, 4, 5, 6]
pairs = list(zip(lst[::2], lst[1::2]))
print(pairs) # [(1, 2), (3, 4), (5, 6)]
6. 滑动窗口
lst = [1, 2, 3, 4, 5]
windows = list(zip(lst, lst[1:], lst[2:]))
print(windows) # [(1, 2, 3), (2, 3, 4), (3, 4, 5)]
这是滑动窗口的经典写法,比手动索引简洁。
四、列表解包的花式玩法
1. 星号解包
first, *rest = [1, 2, 3, 4, 5]
print(first) # 1
print(rest) # [2, 3, 4, 5]
*init, last = [1, 2, 3, 4, 5]
print(init) # [1, 2, 3, 4]
print(last) # 5
a, *mid, b = [1, 2, 3, 4, 5]
print(a, mid, b) # 1 [2, 3, 4] 5
2. 合并列表
a = [1, 2]
b = [3, 4]
c = [*a, *b]
print(c) # [1, 2, 3, 4]
# 合并多个
lists = [[1], [2], [3]]
merged = [*lists[0], *lists[1], *lists[2]]
print(merged) # [1, 2, 3]
3. 解包传参
def add(a, b, c):
return a + b + c
nums = [1, 2, 3]
print(add(*nums)) # 6
4. 解包转置
matrix = [[1, 2], [3, 4], [5, 6]]
transposed = list(zip(*matrix))
print(transposed) # [(1, 3, 5), (2, 4, 6)]
五、列表作为栈和队列的花式用法
1. 栈(后进先出)
stack = []
stack.append(1)
stack.append(2)
stack.append(3)
print(stack.pop()) # 3
print(stack.pop()) # 2
2. 用列表实现队列(不推荐)
queue = []
queue.append(1)
queue.append(2)
print(queue.pop(0)) # 1,O(n)
3. 用 deque 实现队列(推荐)
from collections import deque
queue = deque()
queue.append(1)
queue.append(2)
print(queue.popleft()) # 1,O(1)
4. 用列表模拟固定大小缓冲区
buffer = []
max_size = 3
def add(x):
if len(buffer) >= max_size:
buffer.pop(0) # 删最旧的
buffer.append(x)
add(1); add(2); add(3); add(4)
print(buffer) # [2, 3, 4]
更高效用 deque(maxlen=3):
from collections import deque
buffer = deque(maxlen=3)
buffer.append(1); buffer.append(2); buffer.append(3); buffer.append(4)
print(buffer) # deque([2, 3, 4], maxlen=3)
六、列表和字符串互转的花式用法
1. 字符串转列表
s = "hello"
lst = list(s) # ['h', 'e', 'l', 'l', 'o']
lst = s.split() # 按空白切
lst = s.split(",") # 按逗号切
2. 列表转字符串
words = ["hello", "world"]
s = " ".join(words) # "hello world"
s = ",".join(words) # "hello,world"
s = "".join(words) # "helloworld"
3. 数字列表转字符串
nums = [1, 2, 3]
s = "".join(map(str, nums)) # "123"
s = ",".join(str(x) for x in nums) # "1,2,3"
4. 字符串反转
s = "hello"
reversed_s = "".join(reversed(s)) # "olleh"
reversed_s = s[::-1] # "olleh"
5. 列表元素反转
lst = ["a", "b", "c"]
reversed_lst = lst[::-1] # ['c', 'b', 'a']
reversed_lst = list(reversed(lst)) # ['c', 'b', 'a']
七、列表的统计和聚合
1. 求和、最大、最小
nums = [1, 2, 3, 4, 5]
print(sum(nums)) # 15
print(max(nums)) # 5
print(min(nums)) # 1
print(len(nums)) # 5
2. 平均值
avg = sum(nums) / len(nums) # 3.0
3. 统计元素频率
from collections import Counter
lst = [1, 1, 2, 3, 3, 3]
counter = Counter(lst)
print(counter) # Counter({3: 3, 1: 2, 2: 1})
print(counter.most_common(2)) # [(3, 3), (1, 2)]
4. 用字典手动统计
lst = [1, 1, 2, 3, 3, 3]
freq = {}
for x in lst:
freq[x] = freq.get(x, 0) + 1
print(freq) # {1: 2, 2: 1, 3: 3}
5. all 和 any
nums = [1, 2, 3, 4, 5]
print(all(x > 0 for x in nums)) # True,全部大于 0
print(any(x > 4 for x in nums)) # True,存在大于 4
# 判断列表是否全为真
print(all(nums)) # True
print(all([1, 0, 2])) # False,有 0
6. 列表元素累加
import itertools
nums = [1, 2, 3, 4, 5]
acc = list(itertools.accumulate(nums))
print(acc) # [1, 3, 6, 10, 15]
八、列表的排序花式用法
1. 按绝对值排序
nums = [-3, 1, -2, 4]
nums.sort(key=abs)
print(nums) # [1, -2, -3, 4]
2. 按字符串长度排序
words = ["apple", "hi", "banana"]
words.sort(key=len)
print(words) # ['hi', 'apple', 'banana']
3. 按多个条件排序
students = [("小明", 25), ("小红", 20), ("小刚", 25)]
students.sort(key=lambda x: (x[1], x[0]))
print(students)
# [('小红', 20), ('小刚', 25), ('小明', 25)]
4. 自定义比较函数
from functools import cmp_to_key
def compare(a, b):
if a > b:
return -1
elif a < b:
return 1
return 0
nums = [3, 1, 4, 1, 5]
nums.sort(key=cmp_to_key(compare))
print(nums) # [5, 4, 3, 1, 1],降序
5. 稳定排序
Python 的 sort 是稳定排序,相同 key 的元素保持原顺序。
data = [("A", 2), ("B", 1), ("C", 2), ("D", 1)]
data.sort(key=lambda x: x[1])
print(data)
# [('B', 1), ('D', 1), ('A', 2), ('C', 2)]
# 同 key 的 B 在 D 前,A 在 C 前,保持原顺序
6. 排序后取 Top K
nums = [3, 1, 4, 1, 5, 9, 2, 6]
top3 = sorted(nums, reverse=True)[:3]
print(top3) # [9, 6, 5]
# 更高效:heapq.nlargest
import heapq
top3 = heapq.nlargest(3, nums)
print(top3) # [9, 6, 5]
九、列表的查找和判断
1. 找第一个满足条件的元素
nums = [1, 2, 3, 4, 5]
first_even = next((x for x in nums if x % 2 == 0), None)
print(first_even) # 2
next(生成器, 默认值) 是找第一个匹配项的经典写法,找不到返回默认值。
2. 找所有满足条件的元素
evens = [x for x in nums if x % 2 == 0]
print(evens) # [2, 4]
3. 判断是否包含
print(3 in nums) # True
print(10 not in nums) # True
4. 找最大/最小的索引
nums = [3, 1, 4, 1, 5]
max_idx = nums.index(max(nums))
min_idx = nums.index(min(nums))
print(max_idx, min_idx) # 4 1
5. 找所有匹配的索引
nums = [1, 2, 3, 2, 4, 2]
indices = [i for i, x in enumerate(nums) if x == 2]
print(indices) # [1, 3, 5]
6. 二分查找
import bisect
nums = [1, 3, 5, 7, 9]
print(bisect.bisect_left(nums, 5)) # 2,第一个 >= 5 的位置
print(bisect.bisect_right(nums, 5)) # 3,第一个 > 5 的位置
# 插入并保持有序
bisect.insort(nums, 4)
print(nums) # [1, 3, 4, 5, 7, 9]
十、列表的“黑魔法”
1. 用 * 解包合并
a = [1, 2]
b = [3, 4]
c = [*a, *b, 5]
print(c) # [1, 2, 3, 4, 5]
2. 用 + 和 += 的区别
a = [1, 2]
b = a
a += [3] # 原地修改,a 和 b 都变 [1, 2, 3]
print(b) # [1, 2, 3]
a = [1, 2]
b = a
a = a + [3] # 创建新列表,b 还是 [1, 2]
print(b) # [1, 2]
+= 是原地修改,+ 是创建新列表。
3. 列表的 id 和引用
a = [1, 2, 3]
b = a
print(id(a) == id(b)) # True,同一对象
b = a[:]
print(id(a) == id(b)) # False,不同对象
4. 用列表推导式做“副作用”
# ❌ 不推荐,但能用
[print(x) for x in range(3)]
# 输出 0 1 2,同时生成 [None, None, None]
# ✅ 正确做法
for x in range(3):
print(x)
5. 用 list 的 __contains__ 做自定义判断
class MyList(list):
def __contains__(self, item):
return item in [x * 2 for x in self]
lst = MyList([1, 2, 3])
print(2 in lst) # False,因为列表里没有 4
print(4 in lst) # True,因为 2*2=4
6. 用列表模拟矩阵运算
# 矩阵加法
a = [[1, 2], [3, 4]]
b = [[5, 6], [7, 8]]
result = [[a[i][j] + b[i][j] for j in range(2)] for i in range(2)]
print(result) # [[6, 8], [10, 12]]
# 矩阵乘法
a = [[1, 2], [3, 4]]
b = [[5, 6], [7, 8]]
result = [[sum(a[i][k] * b[k][j] for k in range(2)) for j in range(2)] for i in range(2)]
print(result) # [[19, 22], [43, 50]]
7. 用 zip 实现“分组”
lst = [1, 2, 3, 4, 5, 6, 7, 8]
n = 3
groups = [lst[i:i+n] for i in range(0, len(lst), n)]
print(groups) # [[1, 2, 3], [4, 5, 6], [7, 8]]
8. 用 itertools 做分组
import itertools
lst = [1, 2, 3, 4, 5, 6, 7, 8]
n = 3
groups = list(itertools.zip_longest(*[iter(lst)] * n))
print(groups) # [(1, 2, 3), (4, 5, 6), (7, 8, None)]
9. 用列表推导式做“展平一层”
nested = [[1, 2], [3, [4, 5]], [6]]
flat = [x for sub in nested for x in (sub if isinstance(sub, list) else [sub])]
print(flat) # [1, 2, 3, [4, 5], 6],只展平一层
10. 用 sum 展平列表
nested = [[1, 2], [3, 4], [5, 6]]
flat = sum(nested, [])
print(flat) # [1, 2, 3, 4, 5, 6]
注意:这种写法是 O(n²),只适合小列表。大列表用 itertools.chain。
十一、花式用法 vs 可读性
花式用法虽然巧妙,但可读性往往下降。选择原则:
| 场景 | 推荐 |
|---|---|
| 简单转换 | 列表推导式 |
| 复杂逻辑 | 普通 for 循环 |
| 找第一个匹配 | next((x for x in ...), default) |
| 展平列表 | itertools.chain |
| 转置矩阵 | zip(*matrix) |
| 去重保序 | dict.fromkeys |
| 统计频率 | Counter |
| Top K | heapq.nlargest |
| 滑动窗口 | zip(lst, lst[1:], ...) |
原则:花式用法是工具,不是目的。能用简单写法就别炫技。 团队协作中,可读性 > 简洁性。
十二、一句话总结
| 花式用法 | 写法 |
|---|---|
| 反转 | lst[::-1] |
| 隔一个取 | lst[::2] |
| 原地清空 | lst[:] = [] |
| 展平 | [x for sub in nested for x in sub] |
| 转置 | zip(*matrix) |
| 解包 | a, *rest = lst |
| 合并 | [*a, *b] |
| 转字典 | dict(zip(keys, values)) |
| 反转字典 | {v: k for k, v in d.items()} |
| 找第一个 | next((x for x in lst if ...), None) |
| 去重保序 | list(dict.fromkeys(lst)) |
| 滑动窗口 | zip(lst, lst[1:], lst[2:]) |
| 分组 | [lst[i:i+n] for i in range(0, len(lst), n)] |
| Top K | heapq.nlargest(k, lst) |
| 累加 | itertools.accumulate(lst) |
| 频率 | Counter(lst) |
| 二分查找 | bisect.bisect_left/right |
核心记住:list 的花式用法大多围绕切片、推导式、zip、解包、itertools 展开。它们能让代码更简洁,但可读性优先,别为了炫技而用。