一、python为什么存在深拷贝与浅拷贝?
python中的创建变量的内存分配与c语言中的不一样,是动态存储。c中的是向变量名所代表的地址(指针所指)写入数值,地址即变量名,大小与存储类型是设定好的。而python中创建一个变量是将变量名指向一个对象,因此与c有所区别。也是python有自动回收垃圾对象的原因。
显示具体区别的例子就有拷贝的区别:
x = 10;y = 10;
是在x和y两个指向的地址中写了2个10,而python是将x和y都指向了10这个对象。
因此在某些操作时会产生区别,比如copy。
二、深拷贝与浅拷贝
1.区别
比如都是关于数组的拷贝:
x = [1,2,3]
y = copy.copy(x)
***(
=与浅拷贝的list id是不同的)
浅拷贝是将y指向了创建x时的[1,2,3],此时如果更改内存中的[1,2,3]会同时更改y的值。
x = [1,2,3]
y = copy.deepcopy(x)
此时就是x和y各自指向了一个[1,2,3]的对象了。
2.应用具体例子
二维数组:
此处使用列表方式创建数组,同时记录下.index()方法以及返回二维数组元素索引的方法。
list.index() 函数用于从列表中找出某个值第一个匹配项的索引位置。因此可以用来输出二维列表中的元素位置。此方法仅仅适用于一维数组。
首先创建二维列表:
“=”创建的二维数组:
num=[ [ ] * n ] * m方式:
x = [0,0,0]
num=[ x ] *4
num此时的值为:[[0,0,0],[0,0,0],[0,0,0],[0,0,0]]
如果更改其中一个元素:
num[1][2]=1那么输出:
[[0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 0, 1]]
深拷贝创建:
x = [0, 0, 0] num = [deepcopy(x) for _ in range(4)] num[1][2]=1此时的输出为:
[[0, 0, 0], [0, 0, 1], [0, 0, 0], [0, 0, 0]]
*for _ in range(n) 一般仅仅用于循环n次,不用设置变量,用 _ 指代临时变量,只在这个语句中使用一次。可以代替for i in range(n)。在python3中,range()为序列类型,可以利用 list 函数返回列表,即:
list(range(10))
>>>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
想查找元素在列表的那个位置使用方法:
1.enumerate()方法
array = [["banana", "yam"],["mango", "apple"]]
for i,j in enumerate(array):
if "yam" in j:
index=(i,j.index("yam"))
break
print(index)
2.np.where方法:
a = np.array([["banana", "yam"],["mango", "apple"]])
list(zip(*np.where(a == "yam")))
>> [(0, 1)]
3.index与 enumerate综合:
array = [["banana", "yam"],["mango", "apple"]]
c="yam"
res=[(i, fruits.index(c)) for i, fruits in enumerate(array) if c in fruits]
>>>[(0, 1)]