1. Python中的对象复制
在Python中,对象的复制可以分为两种方式:浅拷贝和深拷贝。浅拷贝是创建一个新的对象,但是仍然保留原有对象中引用对象的地址;而深拷贝则是创建一个完全新的对象,所有的引用都会重新创建。
1.1 浅拷贝
使用浅拷贝时,可以使用对象的copy()方法或者使用Python的copy模块中的copy()方法。
# 使用对象的copy()方法
a = [1, 2, [3, 4]]
b = a.copy()
print("a: ", a) # a: [1, 2, [3, 4]]
print("b: ", b) # b: [1, 2, [3, 4]]
a[0] = 0
print("a: ", a) # a: [0, 2, [3, 4]]
print("b: ", b) # b: [1, 2, [3, 4]]
a[2][0] = 0
print("a: ", a) # a: [0, 2, [0, 4]]
print("b: ", b) # b: [1, 2, [0, 4]]
可以看到,使用对象的copy()方法进行浅拷贝后,当原有对象中有可变对象时,复制过来的新对象和原对象仍然共用这个可变对象。
# 使用Python的copy模块中的copy()方法
import copy
a = [1, 2, [3, 4]]
b = copy.copy(a)
print("a: ", a) # a: [1, 2, [3, 4]]
print("b: ", b) # b: [1, 2, [3, 4]]
a[0] = 0
print("a: ", a) # a: [0, 2, [3, 4]]
print("b: ", b) # b: [1, 2, [3, 4]]
a[2][0] = 0
print("a: ", a) # a: [0, 2, [0, 4]]
print("b: ", b) # b: [1, 2, [0, 4]]
使用Python的copy模块中的copy()方法时,结果与对象的copy()方法相同。
1.2 深拷贝
深拷贝可以使用Python的copy模块中的deepcopy()方法。
import copy
a = [1, 2, [3, 4]]
b = copy.deepcopy(a)
print("a: ", a) # a: [1, 2, [3, 4]]
print("b: ", b) # b: [1, 2, [3, 4]]
a[0] = 0
print("a: ", a) # a: [0, 2, [3, 4]]
print("b: ", b) # b: [1, 2, [3, 4]]
a[2][0] = 0
print("a: ", a) # a: [0, 2, [0, 4]]
print("b: ", b) # b: [1, 2, [3, 4]]
可以看到,使用deepcopy()方法进行深拷贝后,复制过来的新对象和原对象完全相同,不会共用可变对象。
2. 复制自定义对象
对于自定义的对象,可以使用Python的copy模块中的copy()和deepcopy()方法。
例如,定义了一个Person类。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
首先使用copy()方法进行浅拷贝。
import copy
p1 = Person("Tom", 18)
p2 = copy.copy(p1)
print("p1.name: ", p1.name) # p1.name: Tom
print("p2.name: ", p2.name) # p2.name: Tom
p1.name = "Jerry"
print("p1.name: ", p1.name) # p1.name: Jerry
print("p2.name: ", p2.name) # p2.name: Tom
结果显示,使用copy()方法进行浅拷贝时,字符串属性会复制出来新对象,而当属性为可变对象时,复制出来的新对象和原对象仍然共用可变对象。
再使用deepcopy()方法进行深拷贝。
import copy
p1 = Person("Tom", 18)
p2 = copy.deepcopy(p1)
print("p1.name: ", p1.name) # p1.name: Tom
print("p2.name: ", p2.name) # p2.name: Tom
p1.name = "Jerry"
print("p1.name: ", p1.name) # p1.name: Jerry
print("p2.name: ", p2.name) # p2.name: Tom
结果显示,使用deepcopy()方法进行深拷贝时,复制出来的新对象和原对象完全相同,不会共用可变对象。
3. 其他复制方式
除了Python的copy模块提供的copy()和deepcopy()方法外,还有其他的复制方式。
3.1 切片复制
对于列表、元组、字符串等可迭代对象,可以使用切片复制。
a = [1, 2, 3]
b = a[:]
print("a: ", a) # a: [1, 2, 3]
print("b: ", b) # b: [1, 2, 3]
a[0] = 0
print("a: ", a) # a: [0, 2, 3]
print("b: ", b) # b: [1, 2, 3]
可以看到,使用切片复制时,复制出来的新对象和原对象完全不同。
3.2 eval()函数
对于简单的对象,可以使用eval()函数进行复制。
a = [1, 2, 3]
b = eval(repr(a))
print("a: ", a) # a: [1, 2, 3]
print("b: ", b) # b: [1, 2, 3]
a[0] = 0
print("a: ", a) # a: [0, 2, 3]
print("b: ", b) # b: [1, 2, 3]
可以看到,使用eval()函数进行复制时,复制出来的新对象和原对象完全不同。
4. 总结
Python中的对象复制可以采取多种方式:浅拷贝、深拷贝、切片复制、eval()函数等。在使用时需要根据具体情况选择合适的复制方式,以避免出现不必要的错误。