如何在Python中复制对象?

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()函数等。在使用时需要根据具体情况选择合适的复制方式,以避免出现不必要的错误。

后端开发标签