Python3 & 浅拷贝与深拷贝在Python中对象的赋值(=)其实就是对象的引用 。即:当创建一个对象,把它赋值给另一个变量时,python并没有拷贝这个对象,只是拷贝了这个对象的引用而已 。
Python中对象的拷贝分为:浅拷贝(copy)和深拷贝(deepcopy) 。
浅拷贝:拷贝了最外围的对象本身,内部的元素都只是拷贝了一个引用而已 。也就是,将原对象在内存中引用地址拷贝过来 , 然后让新的对象指向这个地址 。可以使用“=”或列表自带的copy()函数(如list.copy()),或使用copy模块的copy()函数 。
深拷贝:外围和内部元素都进行了拷贝对象本身,而不是引用 。即把对象复制一遍,并且该对象中引用的其他对象也同时复制,完全得到一个新的一模一样的对象,对新对象里的值进行修改不会影响原有对象,新对象和原对象完全分离开 。深拷贝只能使用copy模块中deepcopy()函数,使用前要导入:from copy import deepcopy 。
Python中对象分为不可变对象 、可变对象 。
不可变对象:一旦创建就不可修改的对象,例如:字符串、元组、数字
可变对象:可以修改的对象,例如:列表、字典 。
其中Python中的切片可以应用于:列表、元组、字符串,但不能应用于字典 。
而深浅拷贝,可应用于序列(列表、元组、字符串),也可应用于字典 。
其中不可变对象,不管是深拷贝还是浅拷贝,地址值在拷贝后的值都是一样的 。
以下以元组(不可变类型)为例
从上述示例可以看出:
不可变对象类型,没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已 。
所以不可变类型,不管是深拷贝还是浅拷贝,地址值和拷贝后的值都是一样的 。
以下以列表(可变类型)为例
第一种方法:使用=号浅拷贝
输出结果:
第二种方法:使用copy浅拷贝
输出结果:
第三种方法:使用deepcopy深拷贝
输出结果:
从上述示例可以看出:
=浅拷贝:值相等,地址相等
copy浅拷贝:值相等 , 地址不相等
deepcopy深拷贝:值相等,地址不相等
总结:
1,深浅拷贝都是对源对象的复制,占用不同的内存空间 。
2 , 不可变类型的对象,对于深浅拷贝毫无影响,最终的地址值和值都是相等的 。
3,可变类型的对象 , 使用=浅拷贝时 , 值相等 , 地址相等,对新对象里的值进行修改同时会影响原有对象;使用copy浅拷贝时值相等,地址不相等;使用deepcopy深拷贝时值相等,地址不相等 。可以看出针对可变类型copy浅拷贝和deepcopy深拷贝,对新对象里的值进行修改不会影响原有对象 。
python中关于如何在一个函数中把属性设置为列表名的问题,下面这个函数并不会改变列表形式,求指教 。在Python中,对象分为两种:可变对象和不可变对象,不可变对象包括int , float,long,str,tuple等,可变对象包括list,set,dict等 。需要注意的是:这里说的不可变指的是值的不可变 。对于不可变类型的变量 , 如果要更改变量,则会创建一个新值,把变量绑定到新值上,而旧值如果没有被引用就等待垃圾回收 。可变类型数据对对象操作的时候,不需要再在其他地方申请内存,只需要在此对象后面连续申请( /-)即可 , 也就是它的内存地址会保持不变,但区域会变长或者变短 。
在你的change方法中参数对象是个列表,该变量在执行过程中引用了方法外部的I列表 , 在执行到方法的最后,numberlist突然引用了方法内的newlist的地址,这个newlist的是新申请的 。所以并没有改变外部变量I的值 。下面是我写的 , 可以变更外部列表对象的值,因为他直接操作了外部列表内的值
def func_list(a_list):
a_list[0] = 4
t_list = [1, 2, 3]
func_list(t_list)
print t_list
# output: [4, 2, 3]
python中的可变数据类型和不可变数据类型的区别最近在研究某一博主的代码时偶然发现了一个问题,第一反应肯定是我自己知识上的欠缺 。然后经过各种百度啊之类的终于找到了原因 。
上面就是我遇到的问题,按照我的理解,featLabel这个列表经过函数调用后值应该还是空的,如果普通的参数,我的这种理解是完全正确的,但是为什么列表featLabel会跟着改变呢?于是我联想到了java里面的像String这种引用数据类型,貌似他们有几分相似之处 。好了 , 问题说到这,接下来说一下问题的解决 。
在python中的数据可以分为可变数据类型和不变数据类型 。
可变数据类型:
像tuple,list,dict之类的变量就是可变数据类型,变量名存储的是一个地址,该地址指向一个具体的对象,并且不管对变量的值即对象做怎么样的操作,都不会改变变量名存储的地址 。下面是一个例子:
def fun(labels):
dic = [1, 2, 3]
labels.append(dic)
print(id(labels))
return dic
if __name__ == '__main__':
labels = ['hello']
my = fun(labels)
print(labels, '\n', id(labels))
结果如下:
['hello', [1, 2, 3]]
39593224
可见,我们把列表作为参数传入一个函数时,在函数内我们对该列表进行了一些改变 , 由于变量存储的地址没有变(在函数内部和函数外部都是39593224),所以就算我们没有故意通过return语句把该列表传递出来 , 该列表还是会在函数执行结束后跟着改变的 。
不变数据类型:
不变数据类型的对象一旦发生改变,就会在内存中开辟一个新的空间用于存储新的对象,原来的变量名就会指向一个新的地址 。举个例子:
def fun(labels):
labels = 'world'
print(id(labels))
if __name__ == '__main__':
labels = 'hello'
fun(labels)
print(labels, '\n', id(labels))
结果如下:
38578360
hello
39220984
Python的list乘法【巨坑】模式识别要求写混合属性相异性矩阵的算法,我用python语言来写的 。
里面二元矩阵的初始化我直接用的list的乘法,看起来没什么问题 。。初始化完是d = [[0,0,0],[0,0,0],[0,0,0]]
但是判断l[0]和l[1]不同之后 , 除了d[1][0]之外,d[0][0]和d[2][0]都变成了1!
*操作符在实现上是复制了值的引用,而不是创建了新的对象 。所以list的三个item指向的是同一个地址!
*操作符对于不可变对象是安全的,对于可变对象要小心 。
而python里list是可变对象,tuple是不可变对象 。
将上述初始化声明换成以下就ok了
【python函数可变对象 python可变对象都有什么】关于python函数可变对象和python可变对象都有什么的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息 , 记得收藏关注本站 。
推荐阅读
- 钉钉直播数据怎么设置时间,钉钉直播回放时间设置
- 关于anulljavascript的信息
- 微信小程序游戏录视频,小程序录制视频有限制吗
- 如何成为官方推广员英文,怎么样成为推广大使?
- java码点和代码单元 代码单元和代码点
- sap显示未显示的列,sap行项目显示
- 大型网络游戏端游直播软件,游戏直播软件推荐
- ios10怎么打开词频,苹果手机怎么设置词频
- r语言GO可视化 r语言可视化手册 pdf