大家好,小编很高兴在这里见到大家。想必大家也比较喜欢这个领域的新闻,小编当然也很喜欢这样的新闻,废话就不多说了,下面小编就来和大家分享今天精彩的内容!
昨天在编写遗传算法的python实现时犯了一个很低级的错误,导致代码运行结果一直达不到我的期望。于是不得不花费大量的时间和精力检查算法、调试代码,最后终于找到了问题的根源:对python中浅拷贝和深拷贝这一基础概念缺乏应有的。因此我决定用这篇文章来记录这个不起眼的低级错误,也给广大读者提个醒。
引子
在正式介绍python浅拷贝与深拷贝的概念之前,先来看看下图这三个简单的例子。尽管代码简单地令人发指,还是请读者们在心里默默执行一下这三段代码,并将你认为的结果与实际运行结果比对。不出所料,前两段代码只是进行了普通的赋值操作,对变量a的修改不会影响到变量b;第三段代码中列表a中元素的修改也导致了列表b的变化,跟你预想的是否一样呢?
为什么会这样?
昨天我就是在这个问题上栽了跟头,可是为什么会这样呢?百度一番之后,我将原因总结为以下三点:1.在对可变对象进行赋值操作时,得到的只是该对象的引用;2.在对不可变对象进行赋值操作时,将会在内存中复制一份拷副本;3.字典、列表类型的对象为可变对象,整型、字符串、元组等类型的对象为不可变对象。这样就好理解了,前两个例子中变量a都是不可变对象,语句b=a是在内存中复制了a,并将b指向这个拷贝;而在第三个例子中,由于列表a是可变对象,语句b=a只是将b指向了a,a中元素的变化当然会影响到b,同理对b进行修改也会影响到a。
浅拷贝
怎么做才能避免两个可变对象相互影响呢?这里就需要用到python的浅拷贝了,注意使用浅拷贝或深拷贝需要importcopy。浅拷贝的语句为b=copy.copy(a),浅拷贝的原理是在内存中新建一个a的副本,然后将b指向这个副本。下面我们使用浅拷贝对第三个例子的代码进行改造。
运行结果表明,在使用浅拷贝之后,b与a是完全独立的两个变量,列表a的变化不会对b造成任何影响。事实上浅拷贝的用法不止于此,如果变量包含子对象,浅拷贝只会拷贝当前对象,不会拷贝子对象。这句话怎么理解呢?相信看过下面的例子你就明白了。
a中包含子对象“[1,2,3]”,经过浅拷贝后,b虽然与a相互独立,但是为了节省空间没有复制a中的子对象,因此b中的子对象仍然是对a中子对象的引用。所以当a中子对象发生改变时也会造成b中子对象的改变。
深拷贝
到这里自然引出了深拷贝的概念,深拷贝是对原对象深层次的复制,不仅会复制对象本身,也会复制其中的子对象。深拷贝得到的对象与原对象存在于内存中不同的两个区域,两者之前是完全独立的。深拷贝的语句是b=copy.deepcopy(a),话不多说,一起来看下面的代码。
总结
根据浅拷贝和深拷贝的特性,它们通常用于可变对象的复制,如列表和字典,对于不可变对象而言,普通的复制足够了,如整型、字符串、元组。普通赋值、浅拷贝和深拷贝是python很基础的概念,但可能正是因为如此经常被我们忽视。俗话说“基础不牢,地动山摇”,一个小的疏忽很可能造成灾难性的后果,所以在进行更深入学习的同时一定要定期修补基础知识的漏洞。
今天小编给大家带来的文章就到这里了,如果各位有什么想法和看法,欢迎在下面踊跃留言、讨论!小编每一天都会有最新的内容来分享!
领取专属 10元无门槛券
私享最新 技术干货