当前位置:首页>python>Python 中 append、insert 和 extend 有什么区别?

Python 中 append、insert 和 extend 有什么区别?

  • 2026-10-11 07:37:16
Python 中 append、insert 和 extend 有什么区别?

列表里多了一个括号,后面的导入脚本就开始不对劲了。

本来想把 3 条订单明细追加进去,结果列表里塞进去一个“列表”。日志打印出来像这样:

rows = [
    ["A1001", "paid"],
    ["A1002", "paid"],
]

new_rows = [
    ["A1003", "refund"],
    ["A1004", "paid"],
]

rows.append(new_rows)

print(rows)

输出:

[
    ['A1001', 'paid'],
    ['A1002', 'paid'],
    [['A1003', 'refund'], ['A1004', 'paid']]
]

这地方我第一眼就不太信。明明是追加两行,怎么第三个元素变成一个大包了?

问题就在 append。

append 很老实,它不会帮你拆东西。你给它什么,它就把什么原封不动塞到列表最后。

items = ["order_1", "order_2"]

items.append("order_3")
print(items)

结果:

['order_1', 'order_2', 'order_3']

这个没问题。

但你给它一个列表,它也当成一个元素塞进去。

items = ["order_1", "order_2"]

items.append(["order_3", "order_4"])
print(items)

结果:

['order_1', 'order_2', ['order_3', 'order_4']]

所以批量追加数据,用 append 十有八九不是你想要的。

这种场景我一般用 extend。

rows = [
    ["A1001", "paid"],
    ["A1002", "paid"],
]

new_rows = [
    ["A1003", "refund"],
    ["A1004", "paid"],
]

rows.extend(new_rows)

print(rows)

输出才正常:

[
    ['A1001', 'paid'],
    ['A1002', 'paid'],
    ['A1003', 'refund'],
    ['A1004', 'paid']
]

extend 的习惯是:你给我一个可迭代对象,我把里面的元素一个个拿出来,追加到原列表后面。

这句话别看着像概念,坑就在这里。

字符串也是可迭代对象。

tags = ["python", "list"]

tags.extend("api")

print(tags)

输出:

['python', 'list', 'a', 'p', 'i']

如果你只是想追加一个字符串,别用 extend,用 append。

tags = ["python", "list"]

tags.append("api")

print(tags)

输出:

['python', 'list', 'api']

这就是我平时判断它俩的方式:

append 是整体塞进去。

extend 是拆开塞进去。

不是谁更高级,是用途不一样。

再看 insert。

insert 不是追加,它是插队。

比如有一个待处理任务队列,正常任务都往后排,突然来一个补偿任务,要优先跑,但又不能插到最前面,因为第一个任务已经被调度器拿走了。

这种时候就会用 insert。

jobs = [
"sync_user_profile",
"push_order_status",
"clean_tmp_file",
]

jobs.insert(1, "repair_refund_status")

print(jobs)

输出:

[
'sync_user_profile',
'repair_refund_status',
'push_order_status',
'clean_tmp_file'
]

insert(index, value),第一个参数是位置,第二个参数是要插入的东西。

注意,它也是“整体插入”。

jobs = ["job_a", "job_b"]

jobs.insert(1, ["urgent_1", "urgent_2"])

print(jobs)

结果:

['job_a', ['urgent_1', 'urgent_2'], 'job_b']

别指望 insert 自动把列表拆开。它不会。

如果真要在中间插入一批元素,我一般不写循环 insert,那样看着勤快,性能和顺序都容易埋坑。

比如这样就很别扭:

jobs = ["job_a", "job_b", "job_c"]
urgent_jobs = ["fix_1", "fix_2"]

pos = 1
for job in urgent_jobs:
    jobs.insert(pos, job)
    pos += 1

print(jobs)

能跑,但我不太喜欢。列表中间插入,本来就要搬后面的元素,你循环插多次,就是多次搬。

更清楚一点的写法是切片:

jobs = ["job_a", "job_b", "job_c"]
urgent_jobs = ["fix_1", "fix_2"]

jobs[1:1] = urgent_jobs

print(jobs)

输出:

['job_a', 'fix_1', 'fix_2', 'job_b', 'job_c']

这段代码一眼能看出来:从下标 1 的位置,塞进去一批任务。

还有一个小坑,append、insert、extend 都是在原列表上改,不会返回新列表。

下面这种写法,线上脚本里我真见过:

order_ids = ["A1001", "A1002"]

order_ids = order_ids.append("A1003")

print(order_ids)

输出:

None

不是 Python 抽风,是 append() 的返回值就是 None。

正确写法是:

order_ids = ["A1001", "A1002"]

order_ids.append("A1003")

print(order_ids)

extend 和 insert 也是一样。

names = ["tom"]

ret = names.extend(["jerry", "lucy"])

print(names)
print(ret)

输出:

['tom', 'jerry', 'lucy']
None

这种设计其实是在提醒你:我改的是原列表,别拿返回值继续传。

平时写数据清洗脚本,我一般这么分:

单条记录进来,用 append。

bad_rows = []

for line_no, row in enumerate(raw_rows, start=1):
ifnot row.get("user_id"):
        bad_rows.append({"line": line_no, "reason": "missing user_id"})

一批记录合并,用 extend。

all_rows = []

for file_name in import_files:
    rows = load_rows_from_file(file_name)
    all_rows.extend(rows)

指定位置补一个特殊元素,用 insert。

columns = ["user_id", "amount", "created_at"]

if"tenant_id"notin columns:
    columns.insert(0, "tenant_id")

最后再把区别压一下:

append(x):把 x 当成一个元素,放到最后。

extend(xs):遍历 xs,把里面的元素一个个放到最后。

insert(i, x):把 x 当成一个元素,插到下标 i 前面。

真要记,就看这段:

data = [1, 2]

data.append([3, 4])
print(data)      # [1, 2, [3, 4]]

data = [1, 2]
data.extend([3, 4])
print(data)      # [1, 2, 3, 4]

data = [1, 2]
data.insert(1, [3, 4])
print(data)      # [1, [3, 4], 2]

列表这三个方法不难,难的是别在批量数据、任务队列、字段拼接这种地方用顺手了。

尤其看到 append(list) 的时候,最好多看一眼。

它可能不是追加多条数据,只是在列表里塞了一个包。

最新文章

随机文章