头图

大家好,我是涛哥,本文内容来自 涛哥聊Python ,转载请标原创。

更多Python学习内容:http://ipengtao.com

在Python编程中,拷贝对象是一个常见的操作,尤其是在处理复杂数据结构时。Python提供了两种拷贝方式:浅拷贝(shallow copy)和深拷贝(deep copy)。了解这两种拷贝方式的区别和使用场景,对于编写高效和正确的代码至关重要。本文将详细介绍浅拷贝和深拷贝的概念、实现方法及其实际应用,并通过示例代码帮助全面理解这两个重要的工具。

浅拷贝和深拷贝的概念

浅拷贝

浅拷贝创建一个新的对象,但不复制对象内部的子对象。新对象中的子对象仍然引用原对象中的子对象。这意味着对新对象的修改可能会影响原对象,反之亦然。

深拷贝

深拷贝创建一个新的对象,同时递归地拷贝原对象内部的所有子对象。新对象与原对象完全独立,修改新对象不会影响原对象,反之亦然。

使用 copy 模块进行拷贝

Python的copy模块提供了copy函数和deepcopy函数,分别用于实现浅拷贝和深拷贝。

import copy

浅拷贝的实现和示例

使用 copy.copy 进行浅拷贝

copy.copy函数用于创建一个对象的浅拷贝。

import copy

# 创建一个列表
original_list = [1, 2, [3, 4], 5]
# 使用copy.copy进行浅拷贝
shallow_copied_list = copy.copy(original_list)

print("原列表:", original_list)
print("浅拷贝列表:", shallow_copied_list)

# 修改浅拷贝列表中的嵌套列表
shallow_copied_list[2][0] = 99

print("修改后原列表:", original_list)
print("修改后浅拷贝列表:", shallow_copied_list)

输出:

原列表: [1, 2, [3, 4], 5]
浅拷贝列表: [1, 2, [3, 4], 5]
修改后原列表: [1, 2, [99, 4], 5]
修改后浅拷贝列表: [1, 2, [99, 4], 5]

从上述示例可以看出,浅拷贝后的对象与原对象共享内部的嵌套对象,因此修改浅拷贝对象中的嵌套对象会影响原对象。

使用切片操作进行浅拷贝

对于列表,可以使用切片操作进行浅拷贝。

# 使用切片操作进行浅拷贝
shallow_copied_list = original_list[:]

print("原列表:", original_list)
print("浅拷贝列表:", shallow_copied_list)

# 修改浅拷贝列表中的嵌套列表
shallow_copied_list[2][0] = 88

print("修改后原列表:", original_list)
print("修改后浅拷贝列表:", shallow_copied_list)

输出:

原列表: [1, 2, [88, 4], 5]
浅拷贝列表: [1, 2, [88, 4], 5]

切片操作与copy.copy函数的效果相同,都是创建一个新的列表对象,但共享内部的嵌套对象。

深拷贝的实现和示例

使用 copy.deepcopy 进行深拷贝

copy.deepcopy函数用于创建一个对象的深拷贝。

import copy

# 创建一个列表
original_list = [1, 2, [3, 4], 5]
# 使用copy.deepcopy进行深拷贝
deep_copied_list = copy.deepcopy(original_list)

print("原列表:", original_list)
print("深拷贝列表:", deep_copied_list)

# 修改深拷贝列表中的嵌套列表
deep_copied_list[2][0] = 77

print("修改后原列表:", original_list)
print("修改后深拷贝列表:", deep_copied_list)

输出:

原列表: [1, 2, [3, 4], 5]
深拷贝列表: [1, 2, [3, 4], 5]
修改后原列表: [1, 2, [3, 4], 5]
修改后深拷贝列表: [1, 2, [77, 4], 5]

从上述示例可以看出,深拷贝后的对象与原对象完全独立,因此修改深拷贝对象中的嵌套对象不会影响原对象。

拷贝复杂对象

浅拷贝复杂对象

class Person:
    def __init__(self, name, age, address):
        self.name = name
        self.age = age
        self.address = address

    def __repr__(self):
        return f"Person(name={self.name}, age={self.age}, address={self.address})"

original_person = Person("Alice", 30, {"city": "New York", "street": "5th Avenue"})
shallow_copied_person = copy.copy(original_person)

print("原对象:", original_person)
print("浅拷贝对象:", shallow_copied_person)

# 修改浅拷贝对象中的嵌套字典
shallow_copied_person.address["city"] = "San Francisco"

print("修改后原对象:", original_person)
print("修改后浅拷贝对象:", shallow_copied_person)

输出:

原对象: Person(name=Alice, age=30, address={'city': 'San Francisco', 'street': '5th Avenue'})
浅拷贝对象: Person(name=Alice, age=30, address={'city': 'San Francisco', 'street': '5th Avenue'})

深拷贝复杂对象

deep_copied_person = copy.deepcopy(original_person)

print("原对象:", original_person)
print("深拷贝对象:", deep_copied_person)

# 修改深拷贝对象中的嵌套字典
deep_copied_person.address["city"] = "Los Angeles"

print("修改后原对象:", original_person)
print("修改后深拷贝对象:", deep_copied_person)

输出:

原对象: Person(name=Alice, age=30, address={'city': 'San Francisco', 'street': '5th Avenue'})
深拷贝对象: Person(name=Alice, age=30, address={'city': 'Los Angeles', 'street': '5th Avenue'})

拷贝自定义对象

有时,我们可能需要拷贝自定义对象。这时,可以通过实现__copy____deepcopy__方法来定制拷贝行为。

实现自定义浅拷贝

class CustomObject:
    def __init__(self, value):
        self.value = value

    def __copy__(self):
        print("执行自定义浅拷贝")
        return CustomObject(self.value)

original_custom = CustomObject(10)
shallow_copied_custom = copy.copy(original_custom)

print("原对象:", original_custom)
print("浅拷贝对象:", shallow_copied_custom)

实现自定义深拷贝

class CustomObject:
    def __init__(self, value):
        self.value = value

    def __deepcopy__(self, memo):
        print("执行自定义深拷贝")
        return CustomObject(copy.deepcopy(self.value, memo))

original_custom = CustomObject(10)
deep_copied_custom = copy.deepcopy(original_custom)

print("原对象:", original_custom)
print("深拷贝对象:", deep_copied_custom)

注意事项

拷贝不可变对象

对于不可变对象,如整数、字符串和元组,浅拷贝和深拷贝的结果是相同的,因为不可变对象的内容不会改变。

original_int = 42
shallow_copied_int = copy.copy(original_int)
deep_copied_int = copy.deepcopy(original_int)

print("原对象:", original_int)
print("浅拷贝对象:", shallow_copied_int)
print("深拷贝对象:", deep_copied_int)

输出:

原对象: 42
浅拷贝对象: 42
深拷贝对象: 42

循环引用

在处理复杂数据结构时,可能会遇到循环引用的情况。深拷贝能够正确处理循环引用,而浅拷贝可能会导致无限循环。

a = [1, 2, 3]
b = [a, 4, 5]
a.append(b)

deep_copied_a = copy.deepcopy(a)
print("深拷贝对象:", deep_copied_a)

输出:

深拷贝对象: [1, 2, 3

, [[...], 4, 5]]

总结

本文详细介绍了Python中浅拷贝和深拷贝的概念、实现方法及其实际应用场景。通过使用copy模块中的copy函数和deepcopy函数,可以分别实现浅拷贝和深拷贝。浅拷贝创建一个新对象,但不复制内部子对象,而深拷贝则递归地复制所有子对象。文章还展示了如何拷贝复杂对象和自定义对象,以及在处理不可变对象和循环引用时的表现。掌握这些技巧,可以帮助大家在开发过程中更好地管理和操作数据结构,提高代码的健壮性和可维护性。


涛哥聊Python
59 声望37 粉丝