Python 中的对象克隆指的是创建一个完全相同的新对象,新对象包含的所有数据与原始对象相同,但是与原始对象没有关联。对象克隆可以通过多种方式实现,包括浅拷贝和深拷贝。
浅拷贝
浅拷贝会复制原始对象中的引用,而不是对象本身。换句话说,新对象仍然引用原始对象中的相同数据,而不是创建一个新副本。为了创建一个浅拷贝,可以使用原始对象的 copy
方法。
示例1:浅拷贝列表
a = [1,2,[3,4]]
b = a.copy()
# 修改原始对象中的第三个元素
a[2][0] = 5
# 输出新对象和原始对象
print(a) # [1, 2, [5, 4]]
print(b) # [1, 2, [5, 4]]
在上面的例子中,a
是一个包含整数和嵌套列表的列表。创建 b
的流程如下:
b = a.copy()
这将创建一个新列表 b
,其内容与 a
相同。然后,我们将修改 a
的第三个元素,从原来的 [3, 4]
改成了 [5, 4]
。结果,b
的第三个元素也被更改,因为 b
仍然引用 a
中相同的列表。
示例2:浅拷贝自定义对象
我们可以通过定义__copy__()
方法来实现自定义对象的浅拷贝,代码如下:
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def __repr__(self):
return f"Car({self.make!r}, {self.model!r}, {self.year!r})"
def __copy__(self):
return Car(self.make, self.model, self.year)
# 创建两个实例
car1 = Car('Toyota', 'Corolla', 2022)
car2 = car1.__copy__()
# 修改car1
car1.year = 2021
# 输出两个实例
print(car1) # Car('Toyota', 'Corolla', 2021)
print(car2) # Car('Toyota', 'Corolla', 2022)
在上面的例子中,我们定义了一个 Car
类,该类有三个属性:make
,model
和 year
。我们还定义了一个 __copy__
方法,该方法返回一个新的 Car
实例,其属性与原始实例相同。 我们使用 __copy__()
来创建一个新对象 car2
,对car1进行修改后,输出结果表明修改没有影响到car2。
深拷贝
与浅拷贝不同,深拷贝会递归地复制对象及其引用的任何对象。这使得新对象的所有数据都是完全独立的,不受原始对象影响。在 Python 中,可以使用 copy
模块中的 deepcopy
函数来进行深拷贝。
示例3:深拷贝列表
import copy
a = [1,2,[3,4]]
b = copy.deepcopy(a)
# 修改原始对象中的第三个元素
a[2][0] = 5
# 输出新对象和原始对象
print(a) # [1, 2, [5, 4]]
print(b) # [1, 2, [3, 4]]
在上面的例子中,deepcopy
函数使用递归方式复制原始对象和其包含的嵌套列表。最终,b
是一个包含相同数据的新列表,但是与 a
完全独立,所以修改 a
中的嵌套列表不会影响 b
。
示例4:深拷贝自定义对象
我们可以通过定义__deepcopy__()
方法来实现自定义对象的深拷贝,代码如下:
import copy
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def __repr__(self):
return f"Car({self.make!r}, {self.model!r}, {self.year!r})"
def __deepcopy__(self, memo):
return Car(copy.deepcopy(self.make), copy.deepcopy(self.model), copy.deepcopy(self.year))
# 创建两个实例
car1 = Car('Toyota', 'Corolla', [2021, 2022])
car2 = copy.deepcopy(car1)
# 修改car1
car1.year.append(2023)
# 输出两个实例
print(car1) # Car('Toyota', 'Corolla', [2021, 2022, 2023])
print(car2) # Car('Toyota', 'Corolla', [2021, 2022])
在上面的例子中,我们通过定义一个 __deepcopy__()
方法来实现一个能够进行深拷贝的 Car
类。在这个方法中,我们使用 copy.deepcopy()
函数递归地复制对象的每个属性。 在这里我们传递了一个 memo 参数,这是一个字典,用于跟踪已经复制的对象,以便避免递归时的无限循环。 我们用 copy.deepcopy()
方法创建新实例 car2
,最终的输出表明,修改 car1
后并没有影响 car2
。