为什么我需要在Python中复制类实例而不是其他对象类型?

时间:2015-03-22 05:42:16

标签: python python-3.x

当我需要在Python中显式复制对象以便在不改变原始内容的情况下进行更改时,我有点困惑。 Python doc page没有太多细节,只是说“赋值语句不会创建副本”。

示例1:

>>> a = 4
>>> b = a
>>> b += 1
>>> print(b)
>>> print(a)

# Results are what you'd "expect" them to be:
5
4

示例2:

>>> class Test():
>>>     def __init__(self, x):
>>>         self.x = x
>>> 
>>> A = Test(4)
>>> B = A
>>> B.x += 1
>>> print(B.x)
>>> print(A.x)

# Unexpected results because B isn't actually a copy of A:
5
5

为什么这两个例子表现不同?

编辑:为了让示例2起作用,我基本上做了以下操作。我问为什么这不是示例1所必需的:

>>> import copy
>>> A = Test(4)
>>> B = copy.copy(A)
>>> B.x += 1
>>> print(B.x)
>>> print(A.x)

2 个答案:

答案 0 :(得分:2)

在您的示例1中,您编写了b += 1。这与撰写b = b + 1是一回事。这使用=运算符将值分配给b 。您只是更改名称b引用的值。在示例2中,您正在更改两个名称(AB)所引用的对象的属性。它们仍然在内存中引用相同的对象,因此更改该对象的.x属性会同时更改B.xA.x

答案 1 :(得分:2)

a = 4
b = a

..意味着" make b引用a引用的任何内容"。在这种情况下,这将是4。由于整数为immutable,因此通过b更改b += 1会使其指向不同的对象

检查他们的ids

a = 4
b = a

print(id(a)) # Same id
print(id(b)) # Same id

b = 123

print(id(b)) # Different id

当B不是.copy()时,实例A和B也会发生同样的事情。

  

<强> ID (对象)

     

返回对象的“身份”。


mutable 对象的一个​​有趣示例:

l = [1, 2]
k = l

print(id(l)) # Same id
print(id(k)) # Same id

k.append(3)

print(id(k)) # Same id
print(l, k)  # Prints [1, 2, 3] [1, 2, 3]

append()修改kl引用的对象。它没有为k分配不同的对象。

正如@blcckngth所说:

k = k + [3]

print(id(k)) # Different id ..
print(l, k)  # ..prints [1, 2] [1, 2, 3]

k += [3]会导致引用同一个对象。