Python阻止复制对象作为引用

2024-06-02 07:50:59 发布

您现在位置:Python中文网/ 问答频道 /正文

可以在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中可能吗?

提前谢谢。


Tags: 对象实例方法self属性定义initvalue
3条回答

问题是

anotherObject = someObject

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

from copy import copy

anotherObject = copy(someObject)
import copy

obj2 = copy.deepcopy(obj2)

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

import copy
otherObject = copy.copy(someObject)

在这里,copy.copycopy.deepcopy之间的区别很重要-您可以对所描述的简单对象使用copy.copy,但是更嵌套的对象需要copy.deepcopy

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

someObject.value.this_one_has_values_too = 4

或者

someObject.value[0] = 1

或者

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

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

了解这一点的一个很好的方法是使用Online Python Tutor(请参见链接的示例),但是这里是一个简单的行为演示,没有Python教程提供的有用的诊断。

>>> 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时使用该对象。

关于这件事要读的是奈德的Facts and Myths about Python names and values

相关问题 更多 >