python的浅拷贝与深拷贝

1.浅拷贝(Shallow Copy)

在Python中,使用=赋值符号进行拷贝操作,和使用copy()方法进行拷贝操作,得到的均为浅拷贝。

1.1 定义

浅拷贝只复制了原始对象中所包含的元素的引用,而没有复制元素本身,因此,如果修改复制之后的新对象,会影响到原始对象。

1.2 示例

# 定义原始对象

original_list = [[1, 2], [3, 4]]

# 浅拷贝操作

new_list = original_list.copy()

# 修改新对象中的元素

new_list[0][0] = 5

# 打印输出

print('原始对象:', original_list) # 输出:[[5, 2], [3, 4]]

print('浅拷贝的新对象:', new_list) # 输出:[[5, 2], [3, 4]]

通过上述示例,我们可以看到,对新对象中的元素进行修改后,原始对象也受到了影响。

1.3 注意事项

浅拷贝只复制值类型对象本身,而不会复制对象中包含的引用类型对象。

例如:

# 定义包含引用类型对象的原始对象

original_dict = {'key': [1, 2, 3]}

# 浅拷贝操作

new_dict = original_dict.copy()

# 修改新对象中包含的引用类型对象

new_dict['key'][0] = 5

# 打印输出

print('原始对象:', original_dict) # 输出:{'key': [5, 2, 3]}

print('浅拷贝的新对象:', new_dict) # 输出:{'key': [5, 2, 3]}

通过上述示例,我们可以看到,对新对象中包含的引用类型对象进行修改后,原始对象也受到了影响。

2.深拷贝(Deep Copy)

深拷贝则是在复制对象时,将对象及其所有引用类型对象都进行复制,复制后的对象和原始对象互不影响。

2.1 定义

深拷贝会递归复制所有引用类型对象,直到所有的引用类型对象都是值类型对象为止,因此,如果修改复制之后的新对象,不会影响到原始对象。

2.2 示例

# 导入copy模块

import copy

# 定义原始对象

original_dict = {'key': [1, 2, 3]}

# 深拷贝操作

new_dict = copy.deepcopy(original_dict)

# 修改新对象中包含的引用类型对象

new_dict['key'][0] = 5

# 打印输出

print('原始对象:', original_dict) # 输出:{'key': [1, 2, 3]}

print('深拷贝的新对象:', new_dict) # 输出:{'key': [5, 2, 3]}

通过上述示例,我们可以看到,对新对象中包含的引用类型对象进行修改后,原始对象并没有受到影响。

2.3 注意事项

深拷贝会创建一个全新的对象,因此执行深拷贝操作可能会比较耗时。

还有一些特殊情况,例如循环引用的情况,深拷贝操作就会抛出异常。

例如:

# 循环引用的情况

x = [1, 2]

x.append(x)

# 深拷贝操作,会抛出异常

copy.deepcopy(x)

针对这种情况,我们可以使用自定义递归深拷贝方式解决。

def deepcopy(obj):

"""递归实现深拷贝"""

# 如果是值类型对象,则直接拷贝

if not isinstance(obj, (dict, list)):

return obj

# 如果是引用类型对象,则递归拷贝

new_obj = dict() if isinstance(obj, dict) else list()

for key, value in obj.items() if isinstance(obj, dict) else enumerate(obj):

new_obj[key] = deepcopy(value)

return new_obj

# 循环引用的情况

x = [1, 2]

x.append(x)

# 自定义递归深拷贝操作

y = deepcopy(x)

# 打印输出结果

print(x, y)

通过自定义递归深拷贝方式,我们可以避免因循环引用导致深拷贝操作失败。

3.总结

在Python中,浅拷贝和深拷贝的区别在于:浅拷贝只复制元素的引用,而深拷贝会递归复制所有引用类型对象。选择拷贝方式需要根据具体业务场景决定。

对于性能要求比较严格的场景,可以使用浅拷贝方式。而对于需要快速创建全新对象并修改它们的场景,建议使用深拷贝。

后端开发标签