• python中赋值、浅拷贝、深拷贝的区别,几张图片让你学会


    1.赋值

    Python中,对象的赋值都是进行对象引用(内存地址)传递, 赋值(=),就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个

    will = ["Will", 28, ["Python", "C#", "JavaScript"]]
    wilber = will
    print('will>>', will, id(will))
    print('wilber>>', wilber, id(wilber))
    print('will的各个元素id>>', [id(ele) for ele in will])
    print('wilber的各个元素id>>',[id(ele) for ele in wilber])
    print('---'*30)
    will[0] = "Wilber"
    will[2].append("CSS")
    print('will>>', will, id(will))
    print('wilber>>', wilber, id(wilber))
    print('will的各个元素id>>', [id(ele) for ele in will])
    print('wilber的各个元素id>>',[id(ele) for ele in wilber])
    #输出为
    will>> ['Will', 28, ['Python', 'C#', 'JavaScript']] 43988040
    wilber>> ['Will', 28, ['Python', 'C#', 'JavaScript']] 43988040
    will的各个元素id>> [31326928, 493056320, 43988808]
    wilber的各个元素id>> [31326928, 493056320, 43988808]
    ------------------------------------------------------------------------------------------
    will>> ['Wilber', 28, ['Python', 'C#', 'JavaScript', 'CSS']] 43988040
    wilber>> ['Wilber', 28, ['Python', 'C#', 'JavaScript', 'CSS']] 43988040
    will的各个元素id>> [44016672, 493056320, 43988808]
    wilber的各个元素id>> [44016672, 493056320, 43988808]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述

    2.浅拷贝

    浅拷贝会创建一个新的对象,这个例子中”wilber is not will”但是,对于对象中的元素,浅拷贝就只会使用原始元素的引用(内存地址),也就是说”wilber[i] is will[i]”

    当对will进行修改的时候: 由于list的第一个元素是不可变类型,所以will对应的list的第一个元素会使用一个新的对象39758496;

    但是list的第三个元素是一个可变类型,修改操作不会产生新的对象,所以will的修改结果会相应的反应到wilber上

    浅拷贝:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变){1,完全切片方法;2,工厂函数,如list();3,copy模块的copy()函数}
    切片也是浅拷贝

    import copy
    will = ["Will", 28, ["Python", "C#", "JavaScript"]]
    wilber = copy.copy(will)
    print('will>>   ', will, id(will))
    print('wilber>> ', wilber, id(wilber))
    print('will的各个元素id>>  ', [id(ele) for ele in will])
    print('wilber的各个元素id>>',[id(ele) for ele in wilber])
    print('---'*30)
    will[0] = "Wilber"
    will[2].append("CSS")
    print('will>>   ', will, id(will))
    print('wilber>> ', wilber, id(wilber))
    print('will的各个元素id>>  ', [id(ele) for ele in will])
    print('wilber的各个元素id>>',[id(ele) for ele in wilber])
    
    #输出为
    will>>    ['Will', 28, ['Python', 'C#', 'JavaScript']] 43862024
    wilber>>  ['Will', 28, ['Python', 'C#', 'JavaScript']] 43861896
    will的各个元素id>>   [31261392, 493056320, 43862088]
    wilber的各个元素id>> [31261392, 493056320, 43862088]
    ------------------------------------------------------------------------------------------
    will>>    ['Wilber', 28, ['Python', 'C#', 'JavaScript', 'CSS']] 43862024
    wilber>>  ['Will', 28, ['Python', 'C#', 'JavaScript', 'CSS']] 43861896
    will的各个元素id>>   [43886384, 493056320, 43862088]
    wilber的各个元素id>> [31261392, 493056320, 43862088]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述

    3.深拷贝

    跟浅拷贝类似,深拷贝也会创建一个新的对象,这个例子中”wilber is not will” 但是,对于对象中的元素,深拷贝都会重新生成一份(有特殊情况,下面会说明),而不是简单的使用原始元素的引用(内存地址)

    深拷贝:创建一个新的对象,并且递归的复制它所包含的对象(修改其中一个,另外一个不会改变){copy模块的deep.deepcopy()函数}

    import copy
    will = ["Will", 28, ["Python", "C#", "JavaScript"]]
    wilber = copy.deepcopy(will)
    print('will>>   ', will, id(will))
    print('wilber>> ', wilber, id(wilber))
    print('will的各个元素id>>  ', [id(ele) for ele in will])
    print('wilber的各个元素id>>',[id(ele) for ele in wilber])
    print('---'*30)
    will[0] = "Wilber"
    will[2].append("CSS")
    print('will>>   ', will, id(will))
    print('wilber>> ', wilber, id(wilber))
    print('will的各个元素id>>  ', [id(ele) for ele in will])
    print('wilber的各个元素id>>',[id(ele) for ele in wilber])
    # 输出为
    will>>    ['Will', 28, ['Python', 'C#', 'JavaScript']] 37373960
    wilber>>  ['Will', 28, ['Python', 'C#', 'JavaScript']] 37373832
    will的各个元素id>>   [31195856, 493056320, 37374024]
    wilber的各个元素id>> [31195856, 493056320, 37373768]
    ------------------------------------------------------------------------------------------
    will>>    ['Wilber', 28, ['Python', 'C#', 'JavaScript', 'CSS']] 37373960
    wilber>>  ['Will', 28, ['Python', 'C#', 'JavaScript']] 37373832
    will的各个元素id>>   [37398264, 493056320, 37374024]
    wilber的各个元素id>> [31195856, 493056320, 37373768]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    4.特殊情况

    对于非容器类型(如数字、字符串、和其他’原子’类型的对象)没有拷贝这一说
    也就是说,对于这些类型,”obj is copy.copy(obj)” 、”obj is copy.deepcopy(obj)”
    如果元祖变量只包含原子类型对象,则不能深拷贝,看下面的例子
    在这里插入图片描述
    在这里插入图片描述

    import copy
    books=('a','b','c')
    books1,books2 =  copy.copy(books),copy.deepcopy(a)
    >>books is books1 is books2
    # true
    
    a = 'python'
    b,c = copy.copy(a),copy.deepcopy(a)
    In [19]: a is b is c
    Out[19]: True
    In [20]: id(a),id(b),id(c)
    Out[20]: (55466056, 55466056, 55466056)
    
    
    In [30]: t1=('a','b','c',['d'])
    
    In [31]: t2,t3 =  copy.copy(t1),copy.deepcopy(t1)
    
    In [32]: t1 is t2 is t3
    Out[32]: False
    
    In [33]: id(t1), id(t2), id(t3)
    Out[33]: (89247560, 89247560, 88537672)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • Python中对象的赋值都是进行对象引用(内存地址)传递
    • 使用copy.copy(),可以进行对象的浅拷贝,它复制了对象,但对于对象中的元素,依然使用原始的引用.
    • 如果需要复制一个容器对象,以及它里面的所有元素(包含元素的子元素),可以使用copy.deepcopy()进行深拷贝
    • 对于非容器类型(如数字、字符串、和其他’原子’类型的对象)没有被拷贝一说
    • 如果元祖变量只包含原子类型对象,则不能深拷贝

    1.列表的浅拷贝示例

    import copy
    a = [1,2,3,4,['a','b']] #定义一个列表a
    b = a #赋值
    c = copy.copy(a) #浅拷贝
    d = copy.deepcopy(a) #深拷贝
    a.append(5)
    a[0] = '10'
    print('A0',a,id(a))
    
    # [1, 2, 3, 4, ['a', 'b'], 5] #a添加一个元素5
    print('B0',b,id(b))
    # [1, 2, 3, 4, ['a', 'b'], 5] #b跟着添加一个元素5
    print('C0',c,id(c))
    # [1, 2, 3, 4, ['a', 'b']] #c保持不变
    print('D0',d,id(d))
    # [1, 2, 3, 4, ['a', 'b']] #d保持不变
    a[4].append('c')
    a[4][1]='ASDF'
    print('A1',a,id(a))
    # [1, 2, 3, 4, ['a', 'b', 'c'], 5] #a中的list(即a[4])添加一个元素c
    print('B1',b,id(a))
    # [1, 2, 3, 4, ['a', 'b', 'c'], 5] #b跟着添加一个元素c
    print('C1',c,id(c))
    # [1, 2, 3, 4, ['a', 'b', 'c']] #c跟着添加一个元素c
    print('D1',d,id(d))
    [1, 2, 3, 4, ['a', 'b']] #d保持不变
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    2. 单个列表的copy

    names = ['alex','jack','1','mack','racheal','shanshan']
    n2 = names
    n3 = names.copy()
    n4 = names[:]
    
    print('第一轮','names',names,id(names))
    print('第一轮','n2',n2,id(n2))
    print('第一轮','n3',n3,id(n3))
    print('第一轮','n4',n4,id(n4))
    
    names.append('hery')
    names[0]="Alex"
    print('第二轮','names',names,id(names))
    print('第二轮','n2',n2,id(n2))
    print('第二轮','n3',n3,id(n3))
    print('第二轮','n4',n4,id(n4))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    输出:

    第一轮 names ['alex', 'jack', '1', 'mack', 'racheal', 'shanshan'] 167690376
    第一轮 n2 ['alex', 'jack', '1', 'mack', 'racheal', 'shanshan'] 167690376
    第一轮 n3 ['alex', 'jack', '1', 'mack', 'racheal', 'shanshan'] 167692616
    第一轮 n4 ['alex', 'jack', '1', 'mack', 'racheal', 'shanshan'] 167713928
    第二轮 names ['Alex', 'jack', '1', 'mack', 'racheal', 'shanshan', 'hery'] 167690376
    第二轮 n2 ['Alex', 'jack', '1', 'mack', 'racheal', 'shanshan', 'hery'] 167690376
    第二轮 n3 ['alex', 'jack', '1', 'mack', 'racheal', 'shanshan'] 167692616
    第二轮 n4 ['alex', 'jack', '1', 'mack', 'racheal', 'shanshan'] 167713928
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.字符串的copy

    import copy
    name="hahah"   #字符串
    name1=copy.copy(name)
    name2=copy.deepcopy(name)
    print('第一次',id(name),id(name1),id(name2))
    
    sum=111   #数字
    sum1=copy.copy(sum)
    sum2=copy.deepcopy(sum)
    print('第二次',id(sum),id(sum1),id(sum2))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出:

    第一次 31179752 31179752 31179752
    第二次 1702001568 1702001568 1702001568
    
    • 1
    • 2

    4.字典的copy

    '''
    学习中遇到问题没人解答?小编创建了一个Python学习交流群:711312441
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    import copy
    call = {
        'cpu':[80,25],
        'mem':[80,],
        'disk':[80,]
    }
    new_call_1 = copy.copy(call)
    new_call_2 = copy.deepcopy(call)
    print('修改前call1为:%s' %(call),id(call))
    # #修改新模版
    call['disk'] = 66
    call['disk_2'] = 67
    call['cpu'].append(20)
    call['cpu'][1]=11
    new_call_1['cpu'].append(33)
    new_call_1['disk'][0] = 77
    new_call_1['mem'] = 75
    new_call_2['disk'][0] = 79
    # #查看新旧模版的值
    print('call1为:%s' %(call),id(call))
    print('new_call_1为:%s' %(new_call_1),id(new_call_1))
    print('new_call_2为:%s' %(new_call_2),id(new_call_2))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    输出:

    修改前call1为:{'cpu': [80, 25], 'mem': [80], 'disk': [80]} 4411328
    call1为:{'cpu': [80, 11, 20, 33], 'mem': [80], 'disk': 66, 'disk_2': 67} 4411328
    new_call_1为:{'cpu': [80, 11, 20, 33], 'mem': 75, 'disk': [77]} 4452424
    new_call_2为:{'cpu': [80, 25], 'mem': [80], 'disk': [79]} 31977616
    
    • 1
    • 2
    • 3
    • 4

    Python 打印进度条

    import time
    for i in range(0,101,2):
         time.sleep(0.1)
         char_num = i//2      #打印多少个'*'
         per_str = '\r%s%% : %s\n' % (i, '>>>' * char_num) if i == 100 else '\r%s%% : %s'%(i,'*'*char_num)
         print(per_str,end='', flush=True)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    Mybatis动态sql全面详解
    corona接入ios登录和支付
    git使用
    手把手教你使用 Java 在线生成 pdf 文档
    python 中导出requirements.txt 的几种方法
    FastDFS
    Vue2/3 项目中的 ESLint + Prettier 代码检测格式化风格指南
    搭建开发环境
    End-to-End Adversarial-Attention Network for Multi-Modal Clustering
    AWR设置工程仿真频率、原理图仿真频率、默认单位
  • 原文地址:https://blog.csdn.net/qdPython/article/details/126486553