脚本专家 发表于 2026-9-21 15:00:00

Python列表创建与增删改查浅深拷贝常见错误与性能优化

Python列表是使用频率最高的容器类型之一,它有序、可变、可重复,并且可以容纳任意类型元素。列表保存的是对象引用,不是对象本身,因此 a==b 比较内容,a is b 判断是否同一个对象。嵌套可变对象被修改时,外层列表会同步反映,这是排查列表复制类 bug 的关键。


a=; b=; print(a==b, a is b)# True False
x='hello'; z=; lst=
x='world'; z.append(3)
print(lst)# ['hello', ]


创建列表可用字面量、list()、列表推导式、重复乘法、split()、range(),也可从文件、生成器、JSON 等数据源转换。嵌套列表使用乘法要特别小心:[*3]*3 会让三行指向同一个内部列表;正确方式是 [*3 for _ in range(3)]。


matrix_bug=[*3]*3; matrix_bug=1
print(matrix_bug)# [, , ]
matrix_good=[*3 for _ in range(3)]; matrix_good=1
print(matrix_good)# [, , ]
print(list('hello'))# ['h', 'e', 'l', 'l', 'o']
print(list(range(5)))#
print('a,b,c'.split(','))# ['a', 'b', 'c']


索引从 0 开始,负索引 -1 表示最后一个元素。索引越界会抛 IndexError,切片不会越界,会自动截断。遍历列表时,直接遍历元素最简洁;需要序号时可用 enumerate(),同时遍历多个列表可用 zip(),反向遍历用 reversed(),排序后遍历用 sorted()。


fruits=['苹果','香蕉','橘子']
print(fruits, fruits[-1])# 苹果 橘子
nums=
print(nums, nums[::2], nums[::-1])
for i,fruit in enumerate(fruits, start=1):
    print(i, fruit)
for name,score in zip(['小明','小红'],):
    print(name, score)


增删改查方面,修改单个元素可直接下标赋值;切片赋值既能批量替换,也能改变列表长度。append() 在末尾追加一个对象,extend() 把另一个可迭代对象的元素逐个追加,insert() 在指定位置插入。pop() 返回并删除元素,del 按位置删除但不返回,remove() 按值删除第一个匹配项,不存在会抛 ValueError,clear() 清空列表。index() 查找第一次出现的位置,可指定范围,不存在会抛 ValueError;count() 统计出现次数,不存在返回 0。


nums=; nums=20; nums=
print(nums)#
lst=; lst.append()
print(lst)# ]
lst2=; lst2.extend()
print(lst2)#
fruits=['苹果','香蕉','橘子','香蕉']
print(fruits.pop())# 香蕉
print(fruits.index('香蕉'))# 1
nums=; nums.remove(3)
print(nums)#


复制列表时,赋值不是复制。b=a 只是让两个变量指向同一个列表,修改 b 会影响 a。浅拷贝可用 original[:]、list(original)、original.copy()、copy.copy()。浅拷贝只复制第一层,如果列表里嵌套了可变对象,内层仍然共享。需要完全独立时使用 copy.deepcopy(),它会递归复制所有层级,但性能代价更高。只有不可变元素时,浅拷贝通常就够。


a=; b=a; b=100
print(a)#
original=[,]; shallow=original.copy()
original=999
print(shallow)# [, ]
import copy
original=[,]; deep=copy.deepcopy(original)
original=999
print(deep)# [, ]


列表推导式中,条件过滤写在 for 后面;if-else 三元表达式写在 for 前面,用于转换每个元素;多个 if 可连续写,表示同时满足条件。嵌套循环推导式可生成笛卡尔积或提取字段。


evens=
labels=['偶数' if x%2==0 else '奇数' for x in range(5)]
result=
pairs=[(x,y) for x in range(2) for y in range(2)]
print(evens, labels, result, pairs)


性能优化方面,原文提到列表扩容机制、预分配与逐步 append 的对比,以及避免不必要的列表复制。实际写代码时可据此取舍:已知数据规模时优先用列表推导式或预分配,减少逐步扩容;只在需要完全独立副本时才用 deepcopy;浅拷贝能解决时不要深拷贝。列表存引用的特性也会影响嵌套复制、批量收集和函数传参场景。


result=[]
for i in range(10):
    if i % 3 == 0 or i % 5 == 0:
      result.append(i)
print(result)#
squares=
print(squares)#


小结:列表的核心不只在 API 多,而在于理解它是有序可变的引用容器。创建时注意嵌套乘法的引用陷阱,增删改查时区分按位置和按值操作,复制时区分赋值、浅拷贝和深拷贝,推导式注意 if 与 if-else 的位置差异。把这些基础打牢,再进入切片、排序和更复杂的数据处理会顺畅很多。

热心网友6 发表于 2026-9-21 19:00:00

Re: Python列表创建与增删改查浅深拷贝常见错误与性能优化

楼主整理得很全面,尤其是把列表保存对象引用这个点放在最前面,很关键,很多复制类 bug 都是从这里来的。那个 [*3]*3 的例子太经典了,我当年也踩过,三行其实指向同一个内部列表,改一个全都变,后来才记住要用列表推导式。浅拷贝和深拷贝的对比也讲得很清楚,嵌套可变对象时 copy 只复制外层,要完全独立就 deepcopy,但确实要权衡性能。增删改查里 append 和 extend 的区别、pop 和 del 的返回值差异、remove 找不到会报 ValueError 这些细节都很实用。感觉这篇适合当列表操作速查,后面写代码遇到嵌套复制或者批量收集时再回来看看会很有帮助。感谢分享。

热心网友2 发表于 2026-9-21 19:10:00

Re: Python列表创建与增删改查浅深拷贝常见错误与性能优化

写得很细,列表这些坑基本都覆盖到了。我最有共鸣的是“赋值不是复制”和嵌套乘法那两段,b=a 改一个另一个也跟着变,[*3]*3 改一行三行一起变,初学时真的很容易踩。浅拷贝只复制第一层、内层仍然共享这点也很关键,判断标准就是看里面有没有可变对象,有且要完全独立再用 deepcopy。增删改查里切片赋值、append 和 extend 的区别也很实用;remove、index 找不到会抛异常,所以操作前用 in 或 count 判断一下会更稳。列表推导式里过滤条件和三元表达式的位置确实容易混,楼主举的例子很好记。性能部分我也赞同,已知规模优先考虑推导式或预分配,别动不动就 deepcopy。感谢整理,先收藏了,后面写脚本时再回来对照。

热心网友2 发表于 2026-9-21 19:10:00

Re: Python列表创建与增删改查浅深拷贝常见错误与性能优化

楼主这篇整理得很扎实,列表的几个容易翻车的点基本都覆盖了。尤其是 a==b 和 a is b 的区别,以及列表存的是对象引用,嵌套可变对象一改外层就同步变化,这个在排查复制类 bug 时确实很关键。[*3]*3 那里也很经典,三行指向同一个内部列表,改成列表推导式才互相独立,这个坑印象太深了。 增删改查部分把 append 和 extend、pop 和 del 和 remove 的差异写得很清楚,实际写脚本时很容易混。浅拷贝和 deepcopy 的取舍也总结得到位:浅拷贝只复制第一层,嵌套对象仍然共享;需要完全独立才用 deepcopy,但性能代价更高。性能优化上,已知规模时优先用列表推导式或预分配,减少逐步扩容,浅拷贝能解决就别深拷贝,这些取舍很实用。 最后落到“有序可变”加上引用语义,确实把列表的核心讲明白了。感谢分享,这篇适合当备忘录反复看。
页: [1]
查看完整版本: Python列表创建与增删改查浅深拷贝常见错误与性能优化