Python 中的赋值和拷贝

发布于 2021-03-16 10:02:53 字数 3503 浏览 1128 评论 0

赋值

在 python 中,赋值就是建立一个对象的引用,而不是将对象存储为另一个副本。例如:

>>> a=[1,2,3]
>>> b=a
>>> c=a

对象是 [1,2,3],分别由 a、b、c 三个变量其建立了对应的引用关系。而三个变量都不独占对象 [1,2,3],或者说,可以通过任何一个变量来修改 [1,2,3] 这个对象。

>>> c.append(4)
>>> c
[1, 2, 3, 4]
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3, 4]
>>> b.append("from b")
>>> b
[1, 2, 3, 4, 'from b']
>>> a
[1, 2, 3, 4, 'from b']
>>> c
[1, 2, 3, 4, 'from b']

拷贝

拷贝有浅拷贝和深拷贝之分。首先看下面的例子

>>> a=[1,2,3]               #建立a与对象的引用连接
>>> b=a                     #通过赋值,b也与对象建立引用
>>> import copy
>>> c=copy.copy(a)          #浅拷贝,建立了一个[1,2,3]的副本,即一个新的对象
>>> d=copy.deepcopy(a)      #深拷贝,建立了一个[1,2,3]的副本。

至此,a、b、c、d 的关系如下图所示:

a--| |-->[1,2,3] b--|
c----->[1,2,3]
d----->[1,2,3]

修改a

>>> a.append('aa')          #通过变量a修改原对象,使它变成[1,2,3,'aa']
>>> b                       #b也同步改变
[1, 2, 3, 'aa']
>>> c                       #c对应的是一个副本,没有受到影响
[1, 2, 3]
>>> d                       #d同上道理
[1, 2, 3]

a、b、c、d的关系如下图所示:

a--| |-->[1,2,3,'aa'] b--|
c----->[1,2,3]
d----->[1,2,3]

修改 c

>>> c.append("cc")          #修改c的对象
>>> a                       #a没有受到影响,因为a、c是指向不同对象
[1, 2, 3, 'aa']
>>> b
[1, 2, 3, 'aa']
>>> c
[1, 2, 3, 'cc']
>>> d
[1, 2, 3]

a、b、c、d 的关系如下图所示:

a--| |-->[1,2,3,'aa'] b--|
c----->[1,2,3,'cc']
d----->[1,2,3]

在上面的例子中,似乎 copy 和 deepcopy 没有什么区别,都是另外建立一个副本。且看如下例子:

>>> q=[1,2,3,['a','b']]         #注意,这个对象是一个list,里面还有一个元素是list,即q[3]=['a','b']
>>> w=copy.copy(q)              #w、e分别是浅拷贝和深拷贝的副本对象引用
>>> e=copy.deepcopy(q)

>>> q.append('4q')              #q所对应的[1,2,3,['a','b']]变成[1,2,3,['a','b'],'4q']
>>> q
[1, 2, 3, ['a', 'b'], '4q']
>>> w                           #w,e如同前面一样,没有受到影响
[1, 2, 3, ['a', 'b']]
>>> e
[1, 2, 3, ['a', 'b']]

修改 w 的对应列表

>>> w.append(4)
>>> w                           #增加了一个整数4
[1, 2, 3, ['a', 'b'], 4]
>>> q                           #q和e都没有受到影响
[1, 2, 3, ['a', 'b']]
>>> e
[1, 2, 3, ['a', 'b']]
>>> q
[1, 2, 3, ['a', 'b']]

修改 w[3] 的元素,提示:w 是对 q 进行浅拷贝而得。

>>> w[3].append('w3c')
>>> q
[1, 2, 3, ['a', 'b', 'w3c']]
>>> w                               
[1, 2, 3, ['a', 'b', 'w3c'], 4]
>>> e
[1, 2, 3, ['a', 'b']]

仔细观察上面的结果,发现:

  • q 和 w,当修改了列表里面的列表元素之后,两个同步修改了。
  • e 没有受到影响

也就是浅拷贝,只建立了外层的副本,对于内层的副本没有建立;而深拷贝,建立了完整的副本。这就理解了汉语的翻译名称“浅”拷贝之含义了,其“浅”就是拷贝了一层(外层)。

进一步修改 e 看看效果:

>>> e.append('5e')
>>> q
[1, 2, 3, ['a', 'b', 'w3c']]
>>> w
[1, 2, 3, ['a', 'b', 'w3c'], 4]
>>> e
[1, 2, 3, ['a', 'b'], '5e']
>>> e[3].append('e3c')
>>> q
[1, 2, 3, ['a', 'b', 'w3c']]
>>> w
[1, 2, 3, ['a', 'b', 'w3c'], 4]
>>> e
[1, 2, 3, ['a', 'b', 'e3c'], '5e']

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84961 人气
更多

推荐作者

已经忘了多久

文章 0 评论 0

15867725375

文章 0 评论 0

LonelySnow

文章 0 评论 0

走过海棠暮

文章 0 评论 0

轻许诺言

文章 0 评论 0

信馬由缰

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文