Python列表克隆方法全解析

Python列表克隆方法全解析

技术背景

在Python编程中,经常会遇到需要复制列表的场景。然而,直接使用new_list = my_list赋值时,修改new_list会意外地改变my_list,这是因为这种赋值方式只是复制了列表的引用,而不是列表本身。为了避免这种情况,我们需要使用正确的方法来克隆或复制列表。

实现步骤

浅拷贝方法

浅拷贝只复制列表本身,即复制了一个包含原列表中对象引用的新列表。如果原列表中的对象是可变的,修改这些对象会同时影响原列表和浅拷贝后的列表。

  • 使用list.copy()方法(Python 3.3+)
1
2
old_list = [1, 2, 3]
new_list = old_list.copy()
  • 使用切片操作
1
2
old_list = [1, 2, 3]
new_list = old_list[:]
  • 使用list()构造函数
1
2
old_list = [1, 2, 3]
new_list = list(old_list)
  • 使用copy.copy()方法
1
2
3
import copy
old_list = [1, 2, 3]
new_list = copy.copy(old_list)

深拷贝方法

深拷贝会递归地复制列表中的所有对象,包括嵌套的列表和其他容器,创建一个完全独立的副本。

1
2
3
import copy
old_list = [[1, 2], [3, 4]]
new_list = copy.deepcopy(old_list)

核心代码

以下是一个完整的示例,展示了不同复制方法的效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import copy

class Foo(object):
def __init__(self, val):
self.val = val

def __repr__(self):
return f'Foo({self.val!r})'

foo = Foo(1)

a = ['foo', foo]
b = a.copy()
c = a[:]
d = list(a)
e = copy.copy(a)
f = copy.deepcopy(a)

# 编辑原列表和实例
a.append('baz')
foo.val = 5

print(f'original: {a}\nlist.copy(): {b}\nslice: {c}\nlist(): {d}\ncopy: {e}\ndeepcopy: {f}')

最佳实践

  • 根据需求选择合适的复制方法:如果列表只包含不可变对象,浅拷贝通常就足够了;如果列表包含可变对象,如嵌套列表或字典,需要使用深拷贝。
  • 考虑性能因素:不同的复制方法在性能上有所差异。例如,切片操作和list.copy()方法通常比copy.deepcopy()快。在性能敏感的场景中,需要选择合适的方法。以下是一些不同方法的性能测试结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from copy import deepcopy
from time import time

num_times = 100000
L = [None, 'blah', 1, 543.4532,
['foo'], ('bar',), {'blah': 'blah'},
old_class(), new_class()]

t = time()
for i in range(num_times):
Copy(L)
print('Custom Copy:', time() - t)

t = time()
for i in range(num_times):
Copy(L, use_deepcopy=False)
print('Custom Copy Only Copying Lists/Tuples/Dicts (no classes):', time() - t)

t = time()
for i in range(num_times):
copy.copy(L)
print('copy.copy:', time() - t)

t = time()
for i in range(num_times):
copy.deepcopy(L)
print('copy.deepcopy:', time() - t)

t = time()
for i in range(num_times):
L[:]
print('list slicing [:]:', time() - t)

t = time()
for i in range(num_times):
list(L)
print('list(L):', time() - t)

t = time()
for i in range(num_times):
[i for i in L]
print('list expression(L):', time() - t)

t = time()
for i in range(num_times):
a = []
a.extend(L)
print('list extend:', time() - t)

t = time()
for i in range(num_times):
a = []
for y in L:
a.append(y)
print('list append:', time() - t)

t = time()
for i in range(num_times):
a = []
a.extend(i for i in L)
print('generator expression extend:', time() - t)

常见问题

  • 浅拷贝后修改嵌套列表的问题:浅拷贝只复制了外层列表,嵌套列表仍然是共享的。修改嵌套列表会同时影响原列表和浅拷贝后的列表。解决方法是使用深拷贝。
  • eval方法的问题eval方法虽然可以实现深拷贝,但它存在安全风险,特别是在处理不可信的输入时。此外,它的性能也较差,不建议使用。
1
2
3
4
5
6
import timeit
import copy

l = list(range(10))
print(min(timeit.repeat(lambda: copy.deepcopy(l))))
print(min(timeit.repeat(lambda: eval(repr(l)))))

Python列表克隆方法全解析
https://119291.xyz/posts/2025-04-14.python-list-cloning-methods-analysis/
作者
ww
发布于
2025年4月14日
许可协议