17、人工智能Python基础之彻底搞懂赋值、浅拷贝、深拷贝的区别_笔记
# 可变对象与不可变对象
# 可变对象的可变性实质上是指 更改可变对象中的子对象 比如list中的item对象
# 不可变对象:string tuple number
# 可变对象:列表 字典
# 可变对象与不可变对象的赋值有区别:
# 不可变对象进行重新赋值的时候,实际上是将原始值丢弃,将变量指向一个新值,一个新的内存地址
# 可变对象的赋值就是创建了对象的一个新的引用(别名),并不开辟一个新的内存空间
# 浅拷贝与深拷贝只针对可变对象
# 浅拷贝:只拷贝父对象,不拷贝子对象
# 只拷贝了最外围的对象本身,内部的子对象都只是拷贝了一个引用而已
# 浅拷贝:创建一个新的父对象,但它包含的是对原始对象中所有子项的引用,如果用引用的方式修改其中一个对象,另外一个也会改变
# 常见操作:列表的切片[:]操作、使用工厂函数如list/dir/set操作,对象的copy()函数、copy模块的copy()函数(两个一模一样的双胞胎)
# 深拷贝:会拷贝父对象和子对象并且递归的方式拷贝所有的子对象,当对象子对象进行更改的时候,原始对象不会改变。
# 常见操作:copy模块的deepcopy()函数
# 深拷贝不是拷贝子对象的引用 而是拷贝了数据结构
# -*- coding: utf-8 -*-
__author__ = 'dongfangyao'
__date__ = '2018/1/15 下午11:07'
__product__ = 'PyCharm'
__filename__ = 'copy1'
import copy
# 赋值 浅拷贝 深拷贝
# python 可变对象list dict 不可变对象 string tuple number
# str1 = 'dfy'
# print(id(str1))
# str1 = 'dongfangyao'
# print(id(str1))
#
# a = [1, 2, 3]
# a1 = a
# print(id(a))
# print(id(a1))
# a[1] = 22
# print(a)
# print(a1)
# 浅拷贝
# [:] list() set() copy.copy() list.copy()
a = [1, 2, 3]
b = [11, 22, 33]
c = [111, 222, 333]
list1 = [a, b, c]
print('list1的内存地址:' + str(id(list1)))
print('_'*20)
list2 = list1
# print(id(list1) == id(list2))
list3 = list1[:]
# print(id(list1) == id(list3))
# print(id(list1[0][1]) == id(list3[0][1]))
# a[0] = 1111
# list1[0] = 'dfy'
# list1[1][0] = '1111'
# print(list1)
# print(list3)
# 深拷贝 copy.deepcopy()
list4 = copy.deepcopy(list1)
print(id(list1) == id(list4))
print(id(list1[0]) == id(list4[0]))
print(id(list1[0][1]) == id(list4[0][1]))
# a[0] = 1111
# list1[0] = 'dfy'
list1[1][0] = '1111'
print(list1)
print(list4)
复制代码
import copy
list_0 = ["A", "B", ["C", "D"], "E"]
list_1 = copy.copy(list_0)
list_2 = list_0.copy()
list_3 = list_0[:]
list_4 = list(list_0)
list_5 = list_0
# --- 深拷贝的拷贝方式 ---
list_d = copy.deepcopy(list_0)
# --- 深浅拷贝与赋值的区别 ---
# 1. 对第一层数据进行赋值
list_0[0] = "X0"
list_1[0] = "X1"
list_2[0] = "X2"
list_3[0] = "X3"
list_4[0] = "X4"
list_5[0] = "X5"
list_d[0] = "Xd"
# 2. 对第二层的list引用进行赋值
# list_0[2][0] = "Y0"
# list_1[2][0] = "Y1"
# list_2[2][0] = "Y2"
# list_3[2][0] = "Y3"
# list_4[2][0] = "Y4"
# list_5[2][0] = "Y5"
# list_d[2][0] = "Yd"
# 3. 对第一层数据进行赋值
# list_0[3]= "Z0"
# list_1[3]= "Z1"
# list_2[3]= "Z2"
# list_3[3]= "Z3"
# list_4[3]= "Z4"
# list_5[3]= "Z5"
# list_d[3]= "Zd"
print(list_0)
print(list_1)
print(list_2)
print(list_3)
print(list_4)
print(list_5)
print(list_d)
lst = []
a = [1]
lst.append(a)
a[0] = 2
lst.append(a)
print(id(a))
print(lst)
a = [3]
print(id(a))
lst.append(a)
复制代码
第一次是赋值给a的子对象,没有改变a的地址,然后lst中存的又是a的引用,改变了a的子对象的值,就改变了lst中存的引用的值,所以前两个输出是[2] ;
第二次赋值赋给a本身的父对象,因为一个变量同时只能指向一个内存地址的数据,所以a的地址改变了,lst中存入了一个新的引用,所以第三个的输出是[3]