29

是否可以在不复制引用的情况下在 Python 中复制对象?

例如,如果我定义一个类

class SomeClass:
    def __init__(self):
        self.value = 0

然后创建一个实例

someObject = SomeClass()
someObject.value = 12

我尝试将其复制到另一个实例:

anotherObject = someObject

并尝试修改属性,

anotherObject.value = 10

原始属性被修改:

print someObject.value #prints 10

有什么办法可以防止这种情况发生吗?澄清一下,我想要anotherObject.value包含10,但我someObject.value仍然想包含原始的12. 这在python中可能吗?

提前致谢。

4

5 回答 5

38

问题是,随着

anotherObject = someObject

您不复制对象,而只是添加另一个引用。要复制对象,请尝试以下操作:

from copy import copy

anotherObject = copy(someObject)
于 2013-10-06T16:17:12.390 回答
16
import copy

obj2 = copy.deepcopy(obj2)
于 2013-10-06T16:17:28.183 回答
5

正如您所注意到的,anotherObject = someObject不制作副本 - 如果您想要副本,请尝试

import copy
otherObject = copy.copy(someObject)

copy.copyvs的copy.deepcopy区别在这里很重要-您可以摆脱copy.copy所描述的简单对象,但更嵌套的对象将需要copy.deepcopy.

copy.copy(someObject)仅复制 object someObject,但如果someObject包含对其他可以更改的对象(“可变”对象)的引用,如

someObject.value.this_one_has_values_too = 4

或者

someObject.value[0] = 1

或者

someObject.value['key'] = 'value'

然后将在副本中引用这些对象。如果您使用copy.deepcopy,它们也会被复制过来。

了解这一点的一个好方法是使用Online Python Tutor(参见链接示例),但这里是一个直接的行为演示,没有 Online Python Tutor 提供的有用图表。

>>> import copy
>>> class Foo(object):
...     pass
...
>>> f = Foo()
>>> f.value = 1
>>> f.nested_value = [2,3,4]
>>> deep = copy.deepcopy(f)
>>> deep.value = 5
>>> f.value
1
>>> deep.nested_value.append(6)
>>> f.nested_value
[2, 3, 4]
>>> shallow = copy.copy(f)
>>> shallow.value = 7
>>> f.value
1
>>> shallow.nested_value.append(8)
>>> f.nested_value
[2, 3, 4, 8]

编辑:但是第一个例子中的整数呢?f它实际上是在对象和对象之间共享的shallow,但这不是问题——它不可编辑;我们无法将整数对象更改1为任何不同的对象,因此我们不妨节省内存并在任何 Python 对象需要对 1 的引用时使用该对象。

需要阅读的是 Ned's Facts and Myths about Python names and values

于 2013-10-06T16:18:04.157 回答
4
import copy

在某些情况下,只是:

copy_obj = copy.copy(obj)

就足够了,但在其他情况下,您应该使用:

copy_obj = copy.deepcopy(obj)
于 2018-11-20T14:21:08.183 回答
1

你可以使用copy它。尝试以下操作:

someObject = SomeClass()
someObject.value = 12
anotherObject = copy.copy(someObject)
anotherObject.value = 10

现在someObject.value仍然是 12。import copy不过,您必须将其放在脚本的顶部。

于 2013-10-06T16:18:31.113 回答