Python对象拷贝——深拷贝与浅拷贝

python

    • 对象赋值
    • 浅拷贝
    • 深拷贝

1. 对象赋值

对象的赋值实际上是对对象的引用。也就是说当把一个对象赋值给另一个对象时,只是拷贝了引用。如:

python hljs ">>>> t1 = tuple('furzoom')

>>> t2 = t1

>>> id(t1),id(t2)

(139792198303936, 139792198303936)

上面t1和t2代表的是同一个对象。

2. 浅拷贝

除了上面将一个对象直接赋值给另一个对象外,还有两种常用的方法对对象进行拷贝:使用切片操作和工厂方法。

>>> car = ['grand', ['length', 4.85]]

>>> a4 = car[:]

>>> a6 = list(car)

>>> [hex(id(x)) for x in car, a4, a6]

['0x7f23e84da2d8', '0x7f23e84da128', '0x7f23e84da3f8']

通过创建汽车a4和a6,确实表示是不同的对象。现在继续完善a4和a6,修改它们的名字,和汽车长度。

>>> a4[0] = 'a4'

>>> a6[0] = 'a6'

>>> a4, a6

(['a4', ['length', 4.85]], ['a6', ['length', 4.85]])

>>> a4[1][1] = 4.761

>>> a4, a6

(['a4', ['length', 4.761]], ['a6', ['length', 4.761]])

修改汽车名字时,他们表现是正常的,而修改汽车车长时,发生了不期望的结果,修改a4的长度,同时也影响了a6的长度。

为什么会这样呢?原因在于只是针对序列做了浅拷贝。序列类型对象的浅拷贝是默认的拷贝,体现在:使用切片操作[:]、工厂函数、copy模块的copy函数。当改变a6汽车名字时,为什么没有体现在a4汽车上呢?这是因为名字是字符串类型,它是一个不可变类型,改变其内容将引用新建的对象。如下:

>>> a8 = list(car)

>>> [hex(id(x)) for x in car]

['0x7f23e84d7a80', '0x7f23e84da320']

>>> [hex(id(x)) for x in a8]

['0x7f23e84d7a80', '0x7f23e84da320']

>>> [hex(id(x)) for x in a4]

['0x7f23e84d4d78', '0x7f23e84da320']

>>> [hex(id(x)) for x in a6]

['0x7f23e84d4e40', '0x7f23e84da320']

在a4和a6的第二项,它们引用的是同一个对象。

3. 深拷贝

要想避免上面的这种影响,需要对列表进行深拷贝。需要使用copy模块的deepcopy()函数。

如:

>>> car = ['grand', ['length', 4.85]]

>>> a4 = car

>>> import copy

>>> a6 = copy.deepcopy(car)

>>> [hex(id(x)) for x in car, a4, a6]

['0x7f23e84da098', '0x7f23e84da098', '0x7f23e84da440']

>>> a4[0] = 'a4'

>>> a6[0] = 'a6'

>>> a4,a6

(['a4', ['length', 4.85]], ['a6', ['length', 4.85]])

>>> a4[1][1] = 4.761

>>> a4,a6

(['a4', ['length', 4.761]], ['a6', ['length', 4.85]])

另,在copy模块中,只有两个函数,copydeepcopy

以上是 Python对象拷贝——深拷贝与浅拷贝 的全部内容, 来源链接: utcz.com/z/388876.html

回到顶部