Python 列表 append 方法的基本用法
核心概念与调用方式
在 Python 中,列表的 append 方法用于将一个单独的对象追加到列表末尾,并直接修改原列表。它的调用签名是 list.append(obj),返回值是 None,因此通常不将结果赋值给新的变量。
需要注意的是,append 只接受单个对象,无论对象是整数、字符串、元组,还是另一个列表,都会作为一个单独的元素追加到末尾。若传入一个可迭代对象,结果仍然是将该对象作为一个整体添加,而不是将其展开。
# 基本用法示例
lst = [1, 2, 3]
lst.append(4)
print(lst) # [1, 2, 3, 4]
如果你执行 lst.append([4,5]),结果会在列表末尾放入一个子列表,而不是将 4 和 5 作为单独的元素。这就是一个需要关注的点,因为它影响后续的迭代和访问模式。
# 将整个列表作为一个元素追加
lst = [1, 2, 3]
lst.append([4, 5])
print(lst) # [1, 2, 3, [4, 5]]
在时间复杂度方面,append 的平均时间复杂度为常数时间 O(1),但当底层列表容量不足以容纳新元素时,Python 解释器会执行扩容操作,这会涉及将现有元素拷贝到新的内存区域,因此偶发的成本会高于常数时间,但总体是摊销常数时间。
# 简单对比:对大量 append 的时间影响(单位:秒)可作为近似参考
import time
n = 1000000
lst = []
start = time.perf_counter()
for i in range(n):
lst.append(i)
end = time.perf_counter()
print(end - start)
使用场景:什么时候选择 append
逐步构建数据结构
当你需要在循环或逐条处理数据时逐步构建列表,使用 append 将每一条记录追加到末尾,避免一次性创建中间列表。
此外,append 适合合并单个对象到现有集合,例如从数据源读取一条条记录后持续累积。
# 场景示例:逐条读取并累积
lines = []
with open('data.txt','r') as f:
for line in f:
lines.append(line.rstrip('\n'))
如果你需要把多个元素一次性加入,请考虑 extend 或列表连接,而不是多次调用 append,后者在大数据量时会有更高的函数调用开销。
# 不要用 append 循环拼接大量元素,示例用 extend 更高效
data = [1,2,3,4,5]
lst = []
lst.extend(data)
print(lst) # [1, 2, 3, 4, 5]
append 与 extend 的区别
核心差异点
最关键的差异在于:append 向列表末尾添加单一对象,而 extend 迭代给定的可迭代对象,并把其中的元素逐个追加。
另一个要点是:传入一个可迭代对象如列表、元组等,append 会把它作为一个整体添加,而 extend 会展开它的元素。
# append 示例
lst = [1, 2, 3]
lst.append([4, 5])
print(lst) # [1, 2, 3, [4, 5]]
# extend 示例
lst = [1, 2, 3]
lst.extend([4, 5])
print(lst) # [1, 2, 3, 4, 5]
对一个字符串的行为也值得留意:append 会将整个字符串作为一个元素,而 extend 会把字符串拆成单个字符来添加。
# 字符串示例
lst1 = []
lst1.append('ab')
print(lst1) # ['ab']
lst2 = []
lst2.extend('ab')
print(lst2) # ['a', 'b']
在性能角度,append 与 extend 的成本与迭代数量相关,通常在相同数量的元素添加下,两者耗时接近,但多次 append 可能带来更高的函数调用开销。
# 性能对比:简单对比节约度
import time
def bench_append(n):
lst = []
t0 = time.perf_counter()
for i in range(n):
lst.append(i)
t1 = time.perf_counter()
return t1 - t0
def bench_extend(n):
lst = []
t0 = time.perf_counter()
lst.extend(range(n))
t1 = time.perf_counter()
return t1 - t0
print(bench_append(1000000), bench_extend(1000000))
性能分析:append 的时间复杂度与内存影响
时间胸褶与扩容机制
如前所述,append 的摊销时间复杂度为常数时间 O(1),但当现有容量不足时,解释器会触发扩容,涉及拷贝当前元素,成本在短时间内增加。
内存层面,Python 的列表使用连续内存块存放对象引用,扩容时通常会分配更大的空间以减少频繁重新分配。
# 简化说明:内部结构是一个对对象引用的数组
lst = [1,2,3]
print(len(lst), id(lst))
简单的微基准(风险:受硬件影响)可以帮助理解趋势:较高的数据量下,append 的耗时呈现出线性增长的模式,但单次操作维持在较低的常数时间。
# 简单的微基准(风险:受硬件影响)
import time
n = 200000
lst = []
start = time.perf_counter()
for i in range(n):
lst.append(i)
end = time.perf_counter()
print('append time:', end - start)
此外,使用 + 拼接列表会产生额外的拷贝成本,在大规模数据处理场景下往往显著高于单纯的 append 或 extend 的成本。
# 使用 + 拼接的代价示例
a = [1, 2, 3]
b = [4, 5]
c = a + b # 产生新列表并拷贝元素
print(c) 

