一、前言
最近在debug的时候,发现了个python中和C/C++不太一样的地方,就是关于list的复制拷贝问题。
在这里借用这位博主博客中的一句话:
Python没有C语言中的变量。在C语言中,变量不止是个名字,它是字节集合并真实存在于内存某个位置上。而在Python中,变量仅仅是指向对象的标签。
即python中一切的传递都是引用(地址),不存在值传递,无论是赋值还是函数调用。
了解了这句话,开始本次的记录。
二、主要内容
可变对象和不可变对象
在开始之前,我们先来了解两个概念:可变对象
和不可变对象
。
python中,变量保存的是对象的引用,指向堆内存中的对象,在堆中分配的对象分为两类,一类是不可变对象,一类是可变对象。
不可变对象
:
即变量指向的内存中的内容不可改变,所以当更改该对象时,会把原理的值复制到新的空间,然后变量指向这个新的地址。
像数值类型int
,float
,布尔型bool
,字符串str
,元组tuple
等都是不可变对象。
可变对象
:
即变量指向的内存中的内容可以改变。当发生更改时,直接改变的是指向内存中的内容,并没有发生真正的复制行为。
像列表list
,字典dict
,集合set
等都是可变对象。
复制方法详解
在python和其他编程语言中,经常涉及到变量的复制,说到复制,便涉及到浅拷贝和深拷贝。这里拿list举例来讲,深拷贝是指,从old list复制出new list,当其中一个改变时,不会使另一个改变;而浅拷贝相反,当其中任意一个改变时,另一个也会随之改变。下面结合具体实例进行阐述:
常用的复制list的方法有6种,分别是:
1、直接赋值
2、列表生成式
3、切片的方式 [:]
4、for循环逐个添加
5、.copy() / copy.copy(x)的方式
6、 copy.deepcopy()的方式
下面依次结合实例记录。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1、直接赋值
可以看出,直接赋值是非拷贝方法。这两个列表是等价的,修改其中任何一个列表都会影响到另一个列表。
2、列表生成式、切片的方式 [:]、for循环逐个添加、.copy() / copy.copy(x)的方式
列表生成式:
.copy() / copy.copy(x)的方式:
以上只举出了两个例子,原因是以上这四种方法,最后得到的结论都是一样的:
其方法均是一个浅拷贝方法;当发生改变时,新列表可变对象改变,不可对象不发生改变。
另外两种方法,可以自己尝试,具体复制方法如下:
# 切片的方式 [:]
after = before[:]
# for循环逐个添加
after = []
for item in before:
after.append(item)
3、copy.deepcopy()的方式
由上图可以看出,copy.deepcopy()是一种深拷贝方式,即产生的新列表和原来的列表是无关的,是一种比较"纯粹"的方法,哈哈。
结束语
以上就是所记录的内容,希望可以帮助我们coder在debug的时候更顺利。> _ <
参考
参考链接1:python中的引用传递,可变对象,不可变对象
参考链接2:Python中list的复制及深拷贝与浅拷贝探究
参考链接3:[Python] 正确复制列表的方法