导入 copya = \'deepak\'b = 1, 2, 3, 4c = [1, 2, 3, 4]d = {1: 10, 2: 20, 3: 30}a1 = copy.copy(a)b1 = copy.copy(b)c1 = copy.copy(c)d1 = copy.copy(d) print(\'immutable - id(a)==id(a1)\', id(a...
import copy
a = "deepak"
b = 1, 2, 3, 4
c = [1, 2, 3, 4]
d = {1: 10, 2: 20, 3: 30}
a1 = copy.copy(a)
b1 = copy.copy(b)
c1 = copy.copy(c)
d1 = copy.copy(d)
print("immutable - id(a)==id(a1)", id(a) == id(a1))
print("immutable - id(b)==id(b1)", id(b) == id(b1))
print("mutable - id(c)==id(c1)", id(c) == id(c1))
print("mutable - id(d)==id(d1)", id(d) == id(d1))
我得到以下结果:
immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False
如果我执行深度复制:
a1 = copy.deepcopy(a)
b1 = copy.deepcopy(b)
c1 = copy.deepcopy(c)
d1 = copy.deepcopy(d)
结果是一样的:
immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False
如果我进行赋值操作:
a1 = a
b1 = b
c1 = c
d1 = d
结果是:
immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) True
mutable - id(d)==id(d1) True
有人能解释一下这些副本之间到底有什么区别吗?这和可变和不可变对象有关吗?如果是的话,你能给我解释一下吗?
a、b、c、d、a1、b1、c1、d1 是内存中对象的引用,通过它们的 id 唯一标识。
赋值操作获取对内存中对象的引用,并将该引用分配给新名称。 c=[1,2,3,4]
是一个赋值操作,它创建一个包含这四个整数的新列表对象,并将对该对象的引用分配给 c
. c1=c
是一个赋值操作,它获取 对同一对象的相同引用 ,并将其分配给 c1
或 c
访问该列表,发生在该列表上的任何事情都是可见的 c1
,因为它们都引用同一个对象。
c1=copy.copy(c)
是“浅拷贝”,它创建一个新列表,并将对新列表的引用分配给 c1
. c
仍指向原始列表。因此,如果您修改列表 c1
,则引用的列表 c
不会改变。
复制的概念与整数和字符串等不可变对象无关。由于您无法修改这些对象,因此永远不需要在内存中的不同位置拥有相同值的两个副本。因此,整数和字符串以及一些不适用复制概念的其他对象只是被重新分配。这就是为什么您的示例 a
和 b
导致相同的 ID。
c1=copy.deepcopy(c)
是“深层复制”,但在本例中,其功能与浅层复制相同。深层复制与浅层复制的不同之处在于,浅层复制将创建对象本身的新副本,但 内的 本身不会被复制。在您的示例中,列表内只有整数(它们是不可变的),并且如前所述,无需复制它们。因此,深层复制的“深层”部分不适用。但是,请考虑这个更复杂的列表:
e = [[1, 2],[4, 5, 6],[7, 8, 9]]
这是一个包含其他列表的列表(您也可以将其描述为二维数组)。
如果对 运行“浅拷贝” e
,将其复制到 e1
,您会发现列表的 id 发生了变化,但是列表的每个副本都包含对相同三个列表的引用——内部包含整数的列表。这意味着如果您执行 e[0].append(3)
,那么 e
将是 [[1, 2, 3],[4, 5, 6],[7, 8, 9]]
。但 e1
也会是 [[1, 2, 3],[4, 5, 6],[7, 8, 9]]
。另一方面,如果您随后执行 , e.append([10, 11, 12])
, e
将是 [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]
。但 e1
。这是因为外部列表是单独的对象,每个对象最初都包含对三个内部列表的三个引用。如果修改内部列表,无论您是通过一个副本还是另一个副本查看它们,都可以看到这些更改。但是如果您按照上述方式修改其中一个外部列表,那么 [[1, 2, 3],[4, 5, 6],[7, 8, 9]]
包含 e
对原始三个列表的三个引用加上对新列表的一个引用。并且 e1
仍然只包含原始的三个引用。
“深层复制”不仅会复制外部列表,还会进入列表内部并复制内部列表,这样两个结果对象就不会包含任何相同的引用(就可变对象而言)。如果内部列表中有其他列表(或其他对象,如字典),它们也会被复制。这就是“深层复制”的“深层”部分。