目录

一、前言:

二、深拷贝与浅拷贝的异同:

        1.相同点:       

        2.不同点:

        3.形象说明:

        注意:

三、浅拷贝:

 3.1.1浅拷贝示意图:

3.1.2示意图说明

        1.对象与子对象(元素)的关系:

        2.对象:

        3.元素【子对象】:

3.2修改对象:

3.3修改元素(子对象):

3.3.1修改元素(子对象)--可变

3.3.1修改元素(子对象)--不可变

        3.4浅拷贝结论:

四、深拷贝:

4.1深拷贝示意图:

4.2深拷贝:

4.3深拷贝结论:

五、《后续》

5.1修改对象:

        结论2:

5.2修改元素(子对象)

5.2.1修改元素-----可变:

         结论3:

5.2.2修改元素-----不可变:

           结论4:


一、前言:

一、对象与元素、可变与不可变         
        (1)对象:
              对象有存储地址id【就好像某个地址的快递仓库】,对象中的元素都有一个地址id【就像仓库的某某货架】         
        (2)赋值对象指向对象的元素:
               赋值对象或【指向对象】(对象中的元素)有不同的类型【数字,字符串,列表,字典,集合,元组】         
        (3)可变类型与不可变类型:              
                定义:可变就是增删改查之后,对象或元素的存储id不会发生改变,反之就是不可变。   
                1.可变类型:其中【列表,字典,集合】是可变类型                    
                2.不可变类型:【数字,字符串,元组】是不可变数据类型

list1 = [[1, 2], (30, 40),'kkk']
      (4)举例:
         例如以上的列表list1中,有[1, 2]、(30, 40)、'kkk'三个元素,首先列表本身list1是可变的类型,元素[1, 2]是可变的,元素(30, 40)和'kkk'是不可变的

二、深拷贝与浅拷贝的异同:

        1.相同点:       

无论深拷贝还是浅拷贝都会创建一个新对象。即:拷贝出来的对象的id不同。

        2.不同点:

浅拷贝:只拷贝了对象,对象内的元素并不会发生拷贝。
深拷贝:不仅拷贝对象,对象内的元素也会发生拷贝。

        3.形象说明:

深拷贝与浅拷贝形象说明:

首先,有一个数据类型[1,5,6],此时这个数据虽然类型有自己的存储id位置,
但是没有什么意义,因为没有“赋值”给其他的对象,在计算机中“数据没有赋值是没有意义的”。

然后,将数据类型[1,5,6]赋值给一个对象A,也就是A=[1,5,6],此时有了一个对象A,指向了“对象[1,5,6]”,他们是两个不同的id,只是此时是赋值的关系。

然后,深拷贝与浅拷贝都会生成一个新的对象,且与原来的对象是不同的。

然后,浅拷贝---B=copy(A):
     生成了一个新的对象B,没有生成新的“指向对象”,就原来的“指向对象”,
     他们三者的关系是:A----->[1,5,6]<------B
     也就是:浅拷贝得到的【不同对象的“指向对象”是同一个】-----会存在共享部分,也有独立部分

然后,深拷贝--C=deepcopy(A)
     生成了一个新的对象C,也生成了一个新的“指向对象”,
     他们四者间的关系:A----->[1,5,6]
                    C----->[1,5,6]
     也就是:深拷贝得到的【不同对象的“指向对象”是不同的】-----完全独立

        注意:

''' 
如果上面的三者的关系:赋值对象{对象},指向对象,子对象(元素)
没有清楚就不要往下看,不然可能会晕。。。
哈哈哈哈.....
对象可能有子对象[元素],子对象[元素]还有可能有次子对象[元素].......
'''




如A=[8,(9,10),[11,12,(13,14)]]
赋值对象----A
指向对象----[8,(9,10),[11,12,(13,14)]]
一代子对象(元素)----8、(9,10)、[11,12,(13,14)]  三个一代子元素
二代子对象(元素)----9、10、11、12、(13,14)      五个二代子元素  

。。。。。。依次类推

三、浅拷贝:

 3.1.1浅拷贝示意图:

(图示1)

                因为a,b,c三个子对象(元素)可变类型,所以AB是共享abc的,你变我也变。

                因为’kkk‘和d是不可变类型的子对象(元素),所以是AB不共享kkk‘和d的,你变我不变。

(如下)

3.1.2示意图说明

        1.对象与子对象(元素)的关系:

                对象可以包含子对象(元素),对象也可以不包含子对象(元素)。

                比如:A1=[[1,2],{'mame':'Marx','age':'23},'kkk',(30,40),{'Aa','33',14,23}]

                           B2=123

                           对象 A1包含了3个子对象和1个元素

                           对象B2没有包含子对象

        2.对象

                不管被复制的对象A不可变的还是可变的,浅拷贝都会生成一个新的对象。

                不管被复制的对象A不可变的还是可变的,如果直接修改对象,那么浅拷贝得到的对象都不会随之改变

                总结:浅拷贝后,如果直接修改对象,双方不会同步改变。

        3.元素【子对象】

               对象有可能会包含子对象【元素】,也就是嵌套比如元组中有【列表/元组】:([1,2],'name','age',(8,9)),列表中有【字典/元组】:[{'age':12},'age',(11,19)]

             子对象【元素】也有可变与不可变的区分。

              修改:如果被修改的对象不可变的,那么两个对象不会同时改变

                         如果被修改的子对象可变的,那么两个对象同时改变

总结:浅拷贝后,如果修改子对象可变的,那么两个对象同时改变。反之就是不会同时改变。

         1.浅拷贝得到的可变子对象共享,不可变子对象独立

         2.改变共享同时变,改变独立对象不互相影响。

3.2修改对象:

         结论1:直接修改对象,那么浅拷贝得到的对象都不会随之改变

实例:A.append(3)

# encoding=utf-8
import copy

A = [[1, 2], (30, 40), 'kkk']
# A=([1,2],8,9)
B = copy.copy(A)
print(id(A), id(B))
print(A,B)
print(A is B)
print(A[0] is B[0])
print(A[1] is B[1])
print(A[2] is B[2])

print('=============================================')
A.append(3)
print(id(A), id(B))
print(A,B)
print(A is B)
print(A[0] is B[0])
print(A[1] is B[1])
print(A[2] is B[2]) 

        运行结果:没有同时改变

3.3修改元素(子对象):

3.3.1修改元素(子对象)--可变

        结论2:修改子对象是可变的,那么两个对象同时改变

        实例:A[0].append(3)

# encoding=utf-8
import copy

A = [[1, 2], (30, 40), 'kkk']
# A=([1,2],8,9)
B = copy.copy(A)
print(id(A), id(B))
print(A,B)
print(A is B)
print(A[0] is B[0])
print(A[1] is B[1])
print(A[2] is B[2])

print('=============================================')
'''修改可变子对象'''
A[0].append(3)

print(id(A), id(B))
print(A,B)
print(A is B)
print(A[0] is B[0])
print(A[1] is B[1])
print(A[2] is B[2])

        运行结果:同时改变

3.3.1修改元素(子对象)--不可变

        结论3:修改子对象是不可变的,那么两个对象不会同时改变

        实例:A[1]+=(50,)

# encoding=utf-8
import copy

A = [[1, 2], (30, 40), 'kkk']
# A=([1,2],8,9)
B = copy.copy(A)
print(id(A), id(B))
print(A,B)
print(A is B)
print(A[0] is B[0])
print(A[1] is B[1])
print(A[2] is B[2])

print('=============================================')
'''修改不可变子对象'''
A[1]+=(50,)

print(id(A), id(B))
print(A,B)
print(A is B)
print(A[0] is B[0])
print(A[1] is B[1])
print(A[2] is B[2])

运行结果:不同时改变

        3.4浅拷贝结论:

                结论1:浅拷贝会生成一个新的对象。

                结论2:浅拷贝的两个前后对象会共享可变元素(可变子对象)。是否共享决定了他们是否会同步改变。

                结论3:直接修改对象,另一个不会同步改变。

                结论4:如果修改的子对象是可变的【也就是共享的】,那么二者同步改变

                     如果修改的子对象是不可变的【也就是不共享的】,那么二者不会同步改变

浅拷贝的结论还是下面这张图

四、深拷贝:

4.1深拷贝示意图:

4.2深拷贝:

        1.深拷贝后生成了新的一个赋值对象和一个指向对象。
        2.两个赋值对象分别指向了两个不同的指向对象。
        3.两个赋值对象没有改变前的“指向对象的内容是相同”(注意:相同不代表是同一个)的==,但却是不同的两个指向对象 is'''。

        4.深拷贝完全拷贝了父对象及其子对象,两者是完全独立的。

实例如下:

#encoding=UTF-8
from copy import deepcopy

A=[[1, 2], (30, 40),'kkk']

"""1.查看A的存储地址"""
print(id(A))
print(id(A[0]))
print(id(A[1]))
print(id(A[2]))

print('*'*10)

#深拷贝一个对象
B=deepcopy(A)

"""2.查看B的存储地址"""
print(id(B))
print(id(B[0]))
print(id(B[1]))
print(id(B[2]))

"""3.结论1:深拷贝生成的对象完全开辟了新的存储地址,所以有如下判断:"""

print(A is B)       #A并不是B          false
print(A==B)         #A和B是相同的       true
print(A[0] is B[0]) #A[0]并不是B[0]    false
print(A[0]==B[0])   #A[0]和B[0]是相同的 true

深拷贝完全拷贝了父对象及其子对象,两者是完全独立的

4.3深拷贝结论:

                结论:深拷贝完全拷贝了父对象及其子对象,两者是完全独立的,互不再影响。

====================================================================

五、《后续》

从这里开始其实已经是说元素的可变性了,与深拷贝关系不大了,因为深拷贝的两个对象完全独立=====================================================================

5.1修改对象:

        结论2:

               1.深拷贝得到对象与原对象完全独立,两个对象互不再影响。【下面2.3其实是解释】

               2.修改哪个对象,那么只影响被修改的对象,对另外一个不影响。

               3.修改的对象是可变类型,那么被修改的对象的id不会发生变化。

                   修改的对象是不可以变类型,那么被修改的对象的id会发生变化。

实例1:直接在后面添加:A.append(33)

               因为此时的改变对象A本身是列表,是可变类型,所以改变前后A的id没有发生改变

#encoding=UTF-8
from copy import deepcopy

A=[[1, 2], (30, 40),'kkk']

print('==追加前==>')
#深拷贝一个对象
B=deepcopy(A)
print(A,'\n',B)
print(id(A),'\n',id(B))

"""追加一个元素"""
A.append(33)

print('=追加后==>')
print(A,'\n',B)
print(id(A),'\n',id(B))

"""因为此时的改变对象A本身是列表,是可变类型,所以改变前后A的id没有发生改变"""

#小试一下自行判断
print(A is B)
print(A==B)
print(A[0] is B[0])
print(A[0]==B[0])

5.2修改元素(子对象)

5.2.1修改元素-----可变:
         结论3:

               1. 修改对象中的可变元素:

                  被改变对象的元素是可变类型,所以改变前后被修改的元素的id是不变的

实例二:在可变元素后添加:A[0].append(3)

                因为被改变对象的元素A[0]是可变类型,所以改变前后A[0]元素的id是不变的

#encoding=UTF-8
from copy import deepcopy

A=[[1, 2], (30, 40),'kkk']

print('==追加前==>')
#深拷贝一个对象
B=deepcopy(A)
print(A,'\n',B)
print(id(A),'\n',id(B))
print(id(A[0]))

"""可变元素追加一个元素"""
A[0].append(3)

print('=追加后==>')
print(A,'\n',B)
print(id(A),'\n',id(B))
print(id(A[0]))

"""此时因为被改变对象的元素A[0]是可变类型,所以改变前后A[0]元素的id是不变的"""

#小试一下自行判断
print(A is B)
print(A==B)
print(A[0] is B[0])
print(A[0]==B[0])
5.2.2修改元素-----不可变:
           结论4:

                1. 修改对象中的不可变元素:

                  被改变对象的元素是不可变类型,所以改变前后被修改的元素的id是随之改变。

实例三:在不可变元素后添加:A[1]+=(60,)

                因为此时被改变的元素A[1]是不可变的,所以改变前后的元素A[1]的id发生了变化

#encoding=UTF-8
from copy import deepcopy

A=[[1, 2], (30, 40),'kkk']

print('==追加前==>')
#深拷贝一个对象
B=deepcopy(A)
print(A,'\n',B)
print(id(A),'\n',id(B))
print(id(A[1]))

"""不可变元素追加一个元素"""
A[1]+=(60,)

print('=追加后==>')
print(A,'\n',B)
print(id(A),'\n',id(B))
print(id(A[1]))

"""因为此时被改变的元素A[1]是不可变的,所以改变前后的元素A[1]的id发生了变化"""

#小试一下自行判断
print(A is B)
print(A==B)
print(A[1] is B[1])
print(A[1]==B[1])

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐