011、Python数据结构入门:列表(List)的基本操作
011、Python数据结构入门:列表(List)的基本操作
昨天帮实习生调试一段数据处理代码,问题出在一个看似简单的列表操作上。他试图在遍历列表时删除元素,结果数据对不齐,下游计算全乱了。这让我想起自己刚用Python时也踩过同样的坑——列表这东西,用起来顺手,但细节没摸透就容易栽跟头。
列表是什么?
你可以把Python列表想象成工具箱里的那个万能抽屉。螺丝刀、扳手、胶带混着放,随时能往里塞新工具,也能把不用的拿出来。它是有序的容器,能装任何类型的数据,长度还能随时变。别的语言里可能要数组、链表分开学,Python一个列表全搞定。
# 创建列表的几种常见姿势
tools = ['螺丝刀', '扳手', '胶带'] # 最直接的写法
mixed_bag = [42, 'hello', 3.14, True] # 什么都能往里扔,但实际项目别这么混着用
empty_box = [] # 先建个空箱子,后面慢慢装
from_range = list(range(5)) # 从范围生成,得到[0,1,2,3,4]
# 工作中更常见的场景是从文件或数据库读数据
# data_rows = [] # 先声明空列表
# for line in open('data.txt'):
# data_rows.append(line.strip())
核心操作:增删改查
查数据是最基本的。Python的索引从0开始,这个设计坑过无数新手。
items = ['a', 'b', 'c', 'd', 'e']
print(items[0]) # 'a',第一个元素
print(items[-1]) # 'e',倒数第一个,这个技巧很实用
print(items[1:3]) # ['b', 'c'],切片操作,注意右边界不包含
print(items[:3]) # 从头切到索引2
print(items[2:]) # 从索引2切到最后
# 遍历列表的两种方式
for item in items: # 只关心元素本身时用这个
print(f'当前元素: {item}')
for i, item in enumerate(items): # 需要索引时用enumerate,我几乎不用range(len())
print(f'索引{i}处的元素: {item}')
改数据简单直接:
items[0] = 'A' # 把第一个元素改成大写
items[1:3] = ['B', 'C'] # 批量修改切片区域
# items[10] = 'x' # 别这样写!索引越界会报错
添加元素有几个方法,用对了场景代码更清晰:
tools = []
tools.append('锤子') # 最常用,往末尾加一个
tools.extend(['锯子', '钳子']) # 合并另一个列表,比用+号效率高
tools.insert(1, '螺丝刀') # 插到指定位置,后面的元素自动后移
# 注意区别:
tools.append(['电钻', '砂轮机']) # 这样会变成嵌套列表,可能不是你想要的
# 结果是:['锤子', '螺丝刀', '锯子', '钳子', ['电钻', '砂轮机']]
删除操作要小心,特别是遍历时删除:
numbers = [1, 2, 3, 2, 4, 2, 5]
# 按值删除 - 只删第一个匹配的
numbers.remove(2) # 现在列表是[1, 3, 2, 4, 2, 5]
# 按索引删除
del numbers[0] # 删除第一个元素
popped = numbers.pop() # 删除并返回最后一个元素
popped = numbers.pop(1) # 删除指定位置的元素
# 清空列表
numbers.clear() # 比 numbers = [] 更明确表达意图
# 危险操作:遍历时删除
numbers = [1, 2, 3, 4, 5]
# for num in numbers: # 别这样写!会跳过元素或越界
# if num % 2 == 0:
# numbers.remove(num)
# 正确做法:创建新列表或倒序遍历
numbers = [num for num in numbers if num % 2 != 0] # 列表推导式,干净利落
列表的实用技巧
排序和查找是高频操作:
data = [34, 12, 89, 5, 23]
data.sort() # 原地排序,原列表被修改
sorted_data = sorted(data) # 返回新列表,原列表不变
data.sort(reverse=True) # 降序排列
data.sort(key=lambda x: x%10) # 按个位数排序,key参数很强大
# 查找
index = data.index(23) # 找到第一个23的位置
# index = data.index(99) # 值不存在会报错,先用if 99 in data判断
count = data.count(12) # 统计出现次数
列表推导式是Python的精华之一:
# 传统写法
squares = []
for x in range(10):
squares.append(x**2)
# 列表推导式 - 一行搞定
squares = [x**2 for x in range(10)]
# 带条件的推导式
even_squares = [x**2 for x in range(10) if x % 2 == 0]
# 多层循环
pairs = [(x, y) for x in range(3) for y in range(3)]
# 但别过度使用,太复杂的推导式反而难懂
# 如果超过两行逻辑,还是老老实实写for循环
性能陷阱和最佳实践
列表用起来方便,但数据量大时要考虑性能:
# 在开头插入数据很慢
lst = []
for i in range(10000):
lst.insert(0, i) # 每次插入都要移动所有元素
# 在末尾追加很快
lst = []
for i in range(10000):
lst.append(i) # 平均时间复杂度O(1)
# 判断元素是否存在
if target in large_list: # 列表的in操作是O(n),大列表用集合(set)更快
pass
个人经验建议
-
遍历时别修改原列表——这是我见过最多的bug来源。要么创建新列表,要么用倒序遍历,要么用列表推导式。
-
分清深浅拷贝——直接赋值只是起别名,修改会相互影响。需要独立副本时用
list.copy()或list[:]做浅拷贝,嵌套结构要用copy.deepcopy()。 -
列表推导式虽好,别贪杯——简单的转换过滤用推导式很优雅,但三层嵌套还带复杂条件的推导式,过两个月你自己都看不懂。
-
类型尽量一致——实际项目中,一个列表里最好放同类型数据。虽然Python允许混合类型,但处理起来麻烦,也容易出错。
-
大文件别一次性读入列表——处理日志或数据文件时,用生成器逐行处理,内存友好。
列表是Python的瑞士军刀,90%的数据处理场景它都能应付。刚开始写代码时,我总想找“最完美”的写法,现在明白了,代码首先是给人看的,其次是给机器执行的。清晰胜过巧妙,实用胜过花哨。把列表这些基础操作练熟了,后面学字典、集合都是水到渠成的事。
更多推荐



所有评论(0)