gpt4 book ai didi

浅显直白的Python深拷贝与浅拷贝区别说明

转载 作者:我是一只小鸟 更新时间:2023-02-23 06:31:09 26 4
gpt4 key购买 nike

  。

1、可变数据类型与不可变数据类型 。

  在开始说深拷贝与浅拷贝前,我们先来弄清楚,可变对象与不可变对象 。

  总的来说,Python数据类型可分为可变数据类型与不可变数据类型 。

  可变数据类型:在不改变对象所指向的地址的前提下,地址中的值是可以改变的,例如列表[1, 2, 3],我们可以改为[2,3]并不需要变更它指向的地址。列表、字典、集合都是可变数据类型 。

  不可变数据类型:在不改变对象所指向的地址的前提下,地址中的值是不可变的,所以如果修改了对象的值,就相当于在另一个新的地址,存储了新的值。Python中元组、字符串、数值、布尔值都是不可变数据类型.

  。

2、Python深拷贝与浅拷贝的区别 。

  在弄清楚了可变对象和不可变对象之后,我们进入正题,看下Python的深拷贝与浅拷贝的区别 。

  1. 浅拷贝:

   仅拷贝父对象,可理解为仅拷贝对象第一层。浅拷贝之后,新旧对象本身指向的地址不同了,但子对象指向的地址仍然相同,我们可以用copy.copy()和可变数据类型的切片来进行浅拷贝 。

                          m = [1, 0, [2, 3, 4, [5, 6]]]
                          
n = m.copy()
p = m[:]
print(f'对象m的地址是{id(m)},对象n的地址是{id(n)},对象p的地址是{id(p)}')
print(f'm[0]的地址是{id(m[0])},n[0]的地址是{id(n[0])},p[0]的地址是{id(p[0])}')
print(f'm[2]的地址是{id(m[2])},n[2]的地址是{id(n[2])},p[2]的地址是{id(p[2])}')
                          
                            输出:
                            

对象m的地址是1322908811144,对象n的地址是1322908811080,对象p的地址是1322908763400 m[0]的地址是140727539432512,n[0]的地址是140727539432512,p[0]的地址是140727539432512 m[2]的地址是1322908811208,n[2]的地址是1322908811208,p[2]的地址是1322908811208 。

                          
                            打印结果可以看到,浅拷贝之后,新对象n, p的地址与m不同,但n, p的子对象地址与m中子对象地址是相同的
                          
                        

    此时,我们对新对象的子对象进行修改,我们来修改一下n[0]看一下结果 。

                          n[0] =99

                          
                            print
                          
                          (f
                          
                            '
                          
                          
                             m[0]={m[0]}\n n[0]={n[0]}\n p[0]={p[0]}
                          
                          
                            '
                          
                          
                            )

                          
                          
                            print
                          
                          (f
                          
                            '
                          
                          
                             m[0]的地址:{id(m[0])}\n n[0]的地址:{id(n[0])}\n p[0]的地址:{id(p[0])}
                          
                          
                            '
                          
                          
                            )

输出:
 m[0]
                          
                          =1
                          
                            
 n[0]
                          
                          =99
                          
                            
 p[0]
                          
                          =1
                          
                            
 m[0]的地址:
                          
                          140727543364672
                          
                            
 n[0]的地址:
                          
                          140727543367808
                          
                            
 p[0]的地址:
                          
                          140727543364672
                        

    可以看到,n[0]的地址和值都变了, m[0]和p[0]并没有变,是为什么呢?

    记得咱们最开始介绍了可变对象和不可变对象,这里的n[0]是数值,是不可变对象,所以在地址不改变的情况下,它的值是不变的; 。

    而我们在给它赋值时,相当于是把它指向了另一个地址,存储新值,而m[0]和p[0]指向的地址并没有变化 。

    。

  接下来咱们再来尝试变更一下n[2]吧 。

                          
                            print
                          
                          (
                          
                            '
                          
                          
                            ----------------------------修改前----------------------------------\n 
                          
                          
                            '
                          
                          
                            
      f
                          
                          
                            '
                          
                          
                            m[2]的地址:{id(m[2])}\n n[2]的地址:{id(n[2])}\n p[2]的地址:{id(p[2])}
                          
                          
                            '
                          
                          
                            )

n[
                          
                          2][1] = 
                          
                            '
                          
                          
                            n21
                          
                          
                            '
                          
                          
                            print
                          
                          (
                          
                            '
                          
                          
                            ----------------------------修改后----------------------------------\n
                          
                          
                            '
                          
                          
                            
      f
                          
                          
                            '
                          
                          
                             m[2]={m[2]}\n n[2]={n[2]}\n p[2]={p[2]}
                          
                          
                            '
                          
                          
                            )

                          
                          
                            print
                          
                          (f
                          
                            '
                          
                          
                             m[2]的地址:{id(m[2])}\n n[2]的地址:{id(n[2])}\n p[2]的地址:{id(p[2])}
                          
                          
                            '
                          
                          
                            )


输出:

                          
                          ----------------------------修改前----------------------------------
                          
                            
 m[
                          
                          2]的地址:2235118923976
                          
                            
 n[
                          
                          2]的地址:2235118923976
                          
                            
 p[
                          
                          2]的地址:2235118923976
----------------------------修改后----------------------------------
                          
                            
 m[
                          
                          2]=[2, 
                          
                            '
                          
                          
                            n21
                          
                          
                            '
                          
                          , 4, [5, 6
                          
                            ]]
 n[
                          
                          2]=[2, 
                          
                            '
                          
                          
                            n21
                          
                          
                            '
                          
                          , 4, [5, 6
                          
                            ]]
 p[
                          
                          2]=[2, 
                          
                            '
                          
                          
                            n21
                          
                          
                            '
                          
                          , 4, [5, 6
                          
                            ]]
 m[
                          
                          2]的地址:2235118923976
                          
                            
 n[
                          
                          2]的地址:2235118923976
                          
                            
 p[
                          
                          2]的地址:2235118923976
                        

    可以看到,变更前后n[2]、m[2]和p[2]的地址都是没变的, 原因你已经知道了吧,是的,因为n[2]是可变对象,是可以在地址中直接变更值的.

  。

  2. 深拷贝 。

   深拷贝完全父对象与子对象。可使用copy模块的deepcopy()方法进行深拷贝,此外使用for循环复制可迭代序列也是深拷贝 。

                          m = [1, 0, [2, 3, 4, [5, 6
                          
                            ]]]
n1 
                          
                          =
                          
                             copy.deepcopy(m)

                          
                          
                            print
                          
                          (f
                          
                            '
                          
                          
                            对象m的地址是{id(m)},对象n1的地址是{id(n1)}
                          
                          
                            '
                          
                          
                            )

                          
                          
                            print
                          
                          (f
                          
                            '
                          
                          
                            m[0]的地址是{id(m[0])},n1[0]的地址是{id(n1[0])}
                          
                          
                            '
                          
                          
                            )

                          
                          
                            print
                          
                          (f
                          
                            '
                          
                          
                            m[2]的地址是{id(m[2])},n1[2]的地址是{id(n1[2])}
                          
                          
                            '
                          
                          
                            )

输出:
对象m的地址是2551218893640,对象n1的地址是2551219173192
m[0]的地址是140727516494912,n1[0]的地址是140727516494912
m[
                          
                          2]的地址是2551218833480,n1[2]的地址是2551221308040
                        

     打印结果可以看出,新旧对象本身的地址,和可变子对象地址都是不同的.

     这里看到m[0]和n1[0]的地址相同,但不可变对象的值变更地址就会变更,所以不会有问题.

  。

3、 总结 。

  综上,咱们在实际应用中,如果拷贝对象的子对象都是不可变对象,那么使用浅拷贝和深拷贝都行, 。

  但如果待拷贝对象中有可变子对象,需要注意根据实际需求选择使用深拷贝还是浅拷贝.

最后此篇关于浅显直白的Python深拷贝与浅拷贝区别说明的文章就讲到这里了,如果你想了解更多关于浅显直白的Python深拷贝与浅拷贝区别说明的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com