美文网首页
2018-03-31-我复制的变量又双叒叕自己改变了

2018-03-31-我复制的变量又双叒叕自己改变了

作者: 0xC00005 | 来源:发表于2018-04-01 11:47 被阅读0次

前言

还在傻傻的用等号复制变量嘛?a=b?
惊奇,发现改变a的值b的值有时候改变了有时候却不改变qwq
原地爆炸如下:

>>> a=123
>>> b=a
>>> b
123
>>> a
123
>>> b+=100
>>> b
223
>>> a
123
>>> c=[1,2,3]
>>> d=c
>>> d.append(5)
>>> d
[1, 2, 3, 5]
>>> c
[1, 2, 3, 5]
>>> ???????突然智障

一股子智障的气息铺面而来

正文

百度科普了一下复制相关的使用姿势,get到新动作copy库里面的copy和deepcopy【???】
然后又一次入了内存的坑
我以前用的等号复制【我发明的名字】不仅仅会复制对象的值本身,或者说等号复制并不是创建一个新的对象,而是让一个新对象的值指向原来你复制的对象,这样就很有意思了,因为内存地址是唯一的,如果你改变了之前内存地址的值,那么新的对象也就会改变了
这里科普一下一个去Python内存地址的新姿势id(var),使用这个函数可以去任意变量的内存地址
首先我们定义个int类的变量,然后复制并改变:

>>> var = 123
>>> copy_var = var
>>> copy_var ==var #这里证明两个变量的值相等
True
>>> copy_var is var #这里证明两个变量的内存地址相等
True
>>> uncopy_var = 123 #重新定义一个变量,发现结果一样
>>> uncopy_var == var
True
>>> uncopy_var is var
True

这里可能需要瞎扯一下变量与内存的关系【又来了】
因为这里的三个变量都是同样的一个值【这里强调一个单独的变量而不是类似于集合之类的】,Python为了节省内存空间,所以只会开辟一个内存空间......然后把所有同样的变量都指向一个内存地址

>>> print(id(var))
1570861024
>>> print(id(copy_var))
1570861024
>>> print(id(uncopy_var))
1570861024

但是如果我改变其中的某一个值的话

>>> copy_var+=100
>>> copy_var is var
False
>>> print(id(copy_var))
1570864224
>>> print(id(var))      #这里可以很明显的看到加上100内存地址也是一样的加上100
1570861024

我都有点开始怀疑是不是Python专门用这段的内存地址来存储数字来着
【而不是像某些跑得很快的语言是随意分配的】
吓得我重新开了一遍环境:

Python 3.6.3 |Anaconda, Inc.| (default, Oct 15 2017, 03:27:45) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> var = 123
>>> print(id(var))
1570861024

妈耶还真是一样的【开始慌张】
那么集合呢,比如列表

>>> lst=[1,2,3,4]
>>> copy_lst = lst
>>> copy_lst == lst
True
>>> copy_lst is lst
True

现在我改变其中某一些的值。比如我对原来的lst执行压入操作

>>> copy_lst
[1, 2, 3, 4]
>>> lst.append(5)
>>> copy_lst
[1, 2, 3, 4, 5]
>>> lst
[1, 2, 3, 4, 5]

这又是为什么呢【突然智障】
一种解释的方法就是因为列表是多个元素的集合,元素的内存值是不变的,但是这里因为copy_lst的内存地址=lst,所以只要lst改变了copy_lst也会改变,

>>> id(lst[0]) == id(copy_lst[0])#元素内存地址相同
True
>>> id(lst) == id(copy_lst)#列表内存地址相同
True

或者还有另外一种说法,请看下面神奇的微操:

>>> l=[] #这里是一个空列表
>>> c=l #这里我们使用等号把l的值和内存地址复制给c
>>> c == l #都是空列表,所以返回TRUE
True
>>> c is l #等号复制内存地址相同 ,也返回TRUE
True
>>> d =[] #新建一个空列表d
>>> c is d #每一个**新建**的列表的内存地址都是不一样的
False 
>>> c == d #但是都是空列表所以值相同
True

现在导入我们的copy模块

copy.copy 可能是藕断丝连的复制

附:您可能需要导入【woc这么重要的模块都不是内置模块嘛】
我先复制了上面lst的值

import copy
>>> copy.copy_lst=copy.copy(lst)
>>> id(copy.copy_lst) == id(lst)
False

妙哉,但你以为这就完事大吉了?
如果我在列表里面存列表呢?

>>> a=[1,2,[3,4]]  #第三个值为列表[3,4],即内部元素
>>> d=copy.copy(a) #浅拷贝a中的[3,4]内部元素的引用,非内部元素对象的本身
>>> id(a)==id(d)
False
>>> id(a[2])==id(d[2])
True
>>> a[2][0]=3333  #改变a中内部原属列表中的第一个值
>>> d             #这时d中的列表元素也会被改变
[1, 2, [3333, 4]]

惊不惊喜意不意外?
这时候就需要我们的:

copy.deep♂copy 有点黑暗的名字

档然了我们食用的时候请去掉男魂标志
这个方法相比较于之前的copy可不是只是有点黑♂暗而已
他所复制出来的所有的值都是不一样的,相当于重新开辟了一段内存空间来存储

>>> e=copy.deepcopy(a) #e为深拷贝了a
>>> a[2][0]=333 #改变a中内部元素列表第一个的值
>>> e
[1, 2, [3333, 4]] #因为时深拷贝,这时e中内部元素[]列表的值不会因为a中的值改变而改变

最后

参考资料:
copy & deepcopy 浅复制 & 深复制

最后的最后

我求求你们mark一下吧www

相关文章

  • 2018-03-31-我复制的变量又双叒叕自己改变了

    前言 还在傻傻的用等号复制变量嘛?a=b?惊奇,发现改变a的值b的值有时候改变了有时候却不改变qwq原地爆炸如下:...

  • 发表被锁文被锁

    昨日懒懒又双叒叕被锁文了 然后今日懒懒就发表了一篇说明自己又双叒叕被锁了 然后今日文章又双叒叕被锁文了 禁止套娃好...

  • 文又双叕

    文又双叒叕

  • 今日操作:加仓科技、消费,清仓可转债、新能源,减仓机器人

    今日把前段时间加仓的机器人全减完了,消费股又双叒叕跌了,又补了一些。 科技股又双叒叕高开低走,又双叒叕加仓了一些。...

  • 想要过好520,学会这些你才行。| V说饰界

    呦呦呦,又双叒叕520, 妈蛋,单身的老子为什么这么兴奋? 因为……又双叒叕可以表白了啊! 就像每次的12.24、...

  • “又双叒叕”怎么读,又是什么意思?

    当一个人频繁做一件事的时候,比如聚会,我们会说:她又双叒叕聚会了。这个“又双叒叕”是怎么来的呢? 又双叒叕是一个网...

  • 又双叒叕

    哈哈哈,我胡汉三又回来了。(是的,我又重新下载了简书) 半个月前,因为某件事,我把之前写的文章全都删了,今天吃饭无...

  • 又双叒叕

    第一次看见这几个字是在《北美留学生日报》上,当时有一篇文章在说特朗普当选美国总统之后,新政一个接着一个,推特...

  • 又双叒叕

    昨天我又双叒叕忘了来打卡好想把自己打死啊啊啊 又是一年七夕,节日是别人的,狗粮是我的。可能真的是母胎solo单身久...

  • 又双叒叕

    又双叒叕,还有土圭垚、火炏焱燚、水沝淼、屮艸芔茻、口吅品,这些层层叠加而成的字都念什么呢?相信大多数人都不知道,下...

网友评论

      本文标题:2018-03-31-我复制的变量又双叒叕自己改变了

      本文链接:https://www.haomeiwen.com/subject/mcyocftx.html