资讯专栏INFORMATION COLUMN

Python的赋值、浅拷贝、深拷贝

daryl / 1082人阅读

摘要:浅拷贝对一个对象进行拷贝。二不可变对象对于不可变对象,例如数字和字符串而言,赋值浅拷贝和深拷贝没有区别,因为他们的对象引用永远指向同一个内存地址。三可变对象对等数据类型而言,赋值浅拷贝和深拷贝,他们对内存地址的变化是不同的。


在写dict数据类型时,有提到过“赋值语句”与copy()函数。
其实说到深浅拷贝,需要考虑具体的数据类型。一部分是不可变对象,如数字、字符串;另一部分是可变对象,如列表、字典等。


一、定义解释

变量:一个系统表的元素,指向对象的连接空间。

对象:被分配的一块内存,存储其实际的值。

引用:从变量到对象的指针。

不可变对象:一旦创建就不可以修改,如数字、字符串、元组。

可变对象:可以修改的对象,如列表、字典。

赋值:通过语句“=”实现。左边是新建的变量,右边可以是直接内容,或者已存在的变量。是对象的引用,Python没有拷贝该对象,只是拷贝了对象的引用,新变量指向源变量内存地址。

浅拷贝:对一个对象进行拷贝。拷贝最外围的对象本身,内部的元素都只是拷贝了一个引用而已。即新创建了一个类型跟原对象一样、内容是原对象的引用。【浅拷贝对象是新的,对象的引用内容是旧的。】
浅拷贝实现的几种方式:(1)切片:[:];(2)工厂函数,比如list()、dict();(3)使用copy()。

深拷贝:外围和内部元素都进行了拷贝对象本身,而不是引用。即把对象复制一遍,并且该对象中引用的其他对象也复制。

二、不可变对象

对于不可变对象,例如数字和字符串而言,赋值(=)、浅拷贝(copy())和深拷贝(deepcopy())没有区别,因为他们的对象引用永远指向同一个内存地址。
通过例子演示:

>>> var_1 = 123
>>> id(var_1)            # 通过id()查看地址
1615552144
>>> var_2 = var_1
>>> id(var_2)
1615552144
>>>
>>> import copy        # 浅、深拷贝需要导入copy模块
>>> var_3 = copy.copy(var_1)
>>> id(var_3)
1615552144
>>>
>>> var_4 = copy.deepcopy(var_1)
>>> id(var_4)
1615552144

你会发现var_1 ~ var_4 的id指向是一样的。

三、可变对象

对list、dict等数据类型而言,赋值、浅拷贝和深拷贝,他们对内存地址的变化是不同的。
赋值浅拷贝:值相等,地址相等;
copy浅拷贝:值相等,地址不相等;
deepcopy深拷贝:值相等,地址不相等;

例子一:
base[0]=’name’,是一个string,不可变对象;base[1]=[‘age’,18],是list,可变对象。
base_1、base_2均是base的浅拷贝,三者id()一样。
当对第一个string元素进行不同的更改时,发现id各不相同,不会互相影响,因为字符串(不可变)被显示的拷贝,当修改后,新创建了一个字符对象。
而修改第二个list元素时,不同的修改都只对最后一次修改生效,且互相影响,因为第二个元素列表只是简单的复制了其引用,修改任何一个浅拷贝,都会修改引用的内容。

例子二:深拷贝
创建一个字典对象,并使用深拷贝创建一个新的对象。

>>>import copy
>>> var = {"a":1,"b":2,"c":[3,"abc"]}
>>> var1 = copy.deepcopy(var)
>>> id(var),id(var1)
(17616992, 15671136)            # 地址不相同
>>> id(var["c"]),id(var1["c"])
(15695144, 15695384)        
>>> id(var["c"][0]),id(var1["c"][0])
(1615550224, 1615550224)        # ‘c’元素的内存地址是相同的
>>>
>>> var1["c"][0] = 4
>>> var
{"a": 1, "b": 2, "c": [3, "abc"]}
>>> var1
{"a": 1, "b": 2, "c": [4, "abc"]}
>>> id(var["c"][0]),id(var1["c"][0])
(1615550224, 1615550240)        # 对var1的修改没有影响var       

❤ thanks for watching, keep on updating...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/42322.html

相关文章

  • 探索php和python下对象拷贝拷贝

    摘要:对于而言,情况可能会有点小复杂,因为一切皆为对象,所以的普通赋值深拷贝和浅拷贝之间都是有细微区别的。二下的他们在中,对象的赋值和传递都是引用。 一、深拷贝与浅拷贝   深拷贝:赋值时值完全复制,完全的copy,对其中一个作出改变,不会影响另一个   浅拷贝:赋值时,引用赋值,相当于取了一个别名。对其中一个修改,会影响另一个   对于PHP而言,= 赋值时,普通对象是深拷贝,但对对象来说...

    shinezejian 评论0 收藏0
  • 探索php和python下对象拷贝拷贝

    摘要:对于而言,情况可能会有点小复杂,因为一切皆为对象,所以的普通赋值深拷贝和浅拷贝之间都是有细微区别的。二下的他们在中,对象的赋值和传递都是引用。 一、深拷贝与浅拷贝   深拷贝:赋值时值完全复制,完全的copy,对其中一个作出改变,不会影响另一个   浅拷贝:赋值时,引用赋值,相当于取了一个别名。对其中一个修改,会影响另一个   对于PHP而言,= 赋值时,普通对象是深拷贝,但对对象来说...

    wizChen 评论0 收藏0
  • 【编程语言】Python 参数传递、返回值、拷贝拷贝

    摘要:作者本文原载于,不允许转载的参数传递的参数传递,无法控制引用传递还是值传递。对于不可变对象数字字符元组等的参数,更类似值传递对于可变对象列表字典等,更类似引用传递。 作者:LogM 本文原载于 https://segmentfault.com/u/logm/articles ,不允许转载~ 1. Python 的参数传递 Python的参数传递,无法控制引用传递还是值传递。对于不可变对...

    PascalXie 评论0 收藏0
  • 操作之灵魂——拷贝

    摘要:原文地址首先需要搞清楚两个概念赋值和引用,对于操作赋值操作程序先新建对象,然后将的值拷贝到中。切片操作属于浅拷贝。 原文地址 首先需要搞清楚两个概念:赋值和引用,对于操作 target = source: 赋值操作:程序先新建对象target,然后将source的值拷贝到target中。这里,target和source值相同,但是它们是两个完全不同的对象。 引用操作:程序直接将tar...

    codercao 评论0 收藏0
  • python拷贝拷贝

    摘要:之前关于的作用域赋值参数传递,我们接连谈了几篇文章全菊变量和菊部变量关于函数参数传递,人都错了可变对象与不可变对象今天我们依然要就相关话题继续下去。这是由于它们是不可变对象,不存在被修改的可能,所以拷贝和赋值是一样的。 之前关于 Python 的作用域、赋值、参数传递,我们接连谈了几篇文章: 全菊变量和菊部变量 关于函数参数传递,80%人都错了 可变对象与不可变对象 今天我们依然要...

    ideaa 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<