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

个人经验建议

  1. 遍历时别修改原列表——这是我见过最多的bug来源。要么创建新列表,要么用倒序遍历,要么用列表推导式。

  2. 分清深浅拷贝——直接赋值只是起别名,修改会相互影响。需要独立副本时用list.copy()list[:]做浅拷贝,嵌套结构要用copy.deepcopy()

  3. 列表推导式虽好,别贪杯——简单的转换过滤用推导式很优雅,但三层嵌套还带复杂条件的推导式,过两个月你自己都看不懂。

  4. 类型尽量一致——实际项目中,一个列表里最好放同类型数据。虽然Python允许混合类型,但处理起来麻烦,也容易出错。

  5. 大文件别一次性读入列表——处理日志或数据文件时,用生成器逐行处理,内存友好。

列表是Python的瑞士军刀,90%的数据处理场景它都能应付。刚开始写代码时,我总想找“最完美”的写法,现在明白了,代码首先是给人看的,其次是给机器执行的。清晰胜过巧妙,实用胜过花哨。把列表这些基础操作练熟了,后面学字典、集合都是水到渠成的事。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐