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]添加一个值 ```python 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不会变

<br>
对a的第一层对象a[2]进行修改
```python
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的第二层对象进行添加操作 ```python 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

<br>
对a的第二层对象进行修改操作
```python
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()`

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

深拷贝特点

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

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

原文地址:https://www.cnblogs.com/zzliu/p/10662438.html