python中的赋值和深浅拷贝

赋值

在python中,赋值仅仅是复制了对象的引用,并没有开辟内存空间

a = 1
b = a

上述代码只是把a的引用复制给了b,结果是a和b同时指向1

对于可变对象

a = [1, 2, 3]
b = a
b.append(4)

结果a和b都变成了 [1, 2, 3, 4]


浅拷贝(shadow copy)

浅拷贝会创建新对象,其内容不是原对象本身的引用,而是原对象内第一层对象的引用

浅拷贝有三种形式

切片操作

b = a[:] 或者b = [x for x in a]

a = [1, 2, ['a', 'b', [10, 20]]]

# 切片,b的第一层对象与a的第一层对象指向一致
b = a[:]
print(a)  # [1, 2, ['a', 'b', [10, 20]]]
print(b)  # [1, 2, ['a', 'b', [10, 20]]]
print(id(a[2]))  # 1660758488584
print(id(b[2]))  # 1660758488584

a[2]和b[2]的id相同,说明它们指向同一个内存地址



给a的第一层对象a[2]添加一个值

a[2].append('c')
print(a)  # [1, 2, ['a', 'b', [10, 20], 'c']]
print(b)  # [1, 2, ['a', 'b', [10, 20], 'c']]
print(id(a[2]))  # 1660758488584
print(id(b[2]))  # 1660758488584

由于a[2]是列表,是容器类对象,所以添加值后id不会变



对a的第一层对象a[2]进行修改

a[2] = ['c', 'd']
print(a)  # [1, 2, ['c', 'd']]
print(b)  # [1, 2, ['a', 'b', [10, 20], 'c']]
print(id(a))  # 2911387104264
print(id(b))  # 2911387106504
print(id(a[2]))  # 1660758488712
print(id(b[2]))  # 1660758488584

可以看到a和b是两个不同的对象,对a[2]进行赋值,把a[2]指向另一个对象,因此a和b就不同了



对a的第二层对象进行添加操作

a[2][2].append(30)
print(a)  # [1, 2, ['a', 'b', [10, 20, 30]]]
print(b)  # [1, 2, ['a', 'b', [10, 20, 30]]]
print(id(a[2]))  # 1721086473736
print(id(b[2]))  # 1721086473736
print(id(a[2][2]))  # 1721086473800
print(id(b[2][2]))  # 1721086473800

添加操作仍然不会改变id



对a的第二层对象进行修改操作

a[2][2] = ['love', 'sweet']
print(a)  # [1, 2, ['a', 'b', ['love', 'sweet']]]
print(b)  # [1, 2, ['a', 'b', ['love', 'sweet']]]
print(id(a[2]))  # 2389899703816
print(id(b[2]))  # 2389899703816
print(id(a[2][2]))  # 2389899703944
print(id(b[2][2]))  # 2389899703944


工厂函数

b = list(a)


copy 函数

b = copy.copy(a)


小结

浅拷贝特点

  • 重新创建对象
  • 内容是第一层对象的引用
  • 修改第一层对象不会相互影响,修改第二层及以上会相互影响


深拷贝

深拷贝只有一种形式,copy.deepcopy()

深拷贝和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。因此,它的时间和空间开销要高。

深拷贝特点

  • 完全拷贝,新对象与原对象没有一点关系
  • 开销大

注意:对于数字、字符串没有拷贝一说,只有对象的引用

猜你喜欢

转载自www.cnblogs.com/zzliu/p/10662438.html