面试中出现了深拷贝、浅拷贝的问题,但由于平时很重视实现功能,忽视了基础原理,对其理解很模糊。 所以,我决定好好学习和整理基础。
Python是简单代入、浅拷贝、深拷贝的“拷贝”方式
一、赋值
赋值是这三种操作中最常见的。 让我们用几个例子来分析赋值操作。str示例:
a='hello '。
b='hello '。
c=a
d=[用于x的标识] [ a,b,c ]
print(d )为
结果: [ 2563139949320,2563139949320,2563139949320,2563139949320 ]
可以看出a、b、c三者的地址相同。 因此,以上的代入操作相当于c=a=b='hello '。
赋值是指系统将内存分配给变量或对象' hello ',然后将地址分配给a、b和c。 所以那些地址是一样的。
list示例
a=“问候”
b=“问候”
c=a
d=[用于x的标识] [ a,b,c ]
print(d )为
结果: [ 2255353887816,2255354865992,2255353887816 ]
但是,这种情况不同。 a和b的地址不一样。 为什么?
因为str不是可变的,所以同一个“hello”只有一个地址,但是list是可变的,所以必须分配两个地址。
这个时候,我们想探索一下这两种情况如果修改了值会怎么样。
str示例
a='word '足球俱乐部
d=[用于x的标识] [ a,b,c ]
print(d )为
打印(a,b,c ) )。
结果: [ 2186334765440,2186333901576,218633901576 ]
# #魔兽世界
这时,a的地址和值发生了变化,但b、c的地址和值没有变化。 由于没有str的偏差,a要重新代入值就需要重新开放存储器空间,所以a的值会发生变化,a指向的地址也会发生变化。 b、c由于“hello”的不变性,因此不发生变化。
list示例
世界足球锦标赛
d=[用于x的标识] [ a,b,c ]
print(d )为
打印(a,b,c ) )。
结果: [ 2365031267400,2365032245576,2365031267400 ]
# #“word”“问候”“word”
此时,a、c的值和地址会发生变化,但两者保持不变,b也不变。 由于list的可变性,更改list的值不需要另外留出空间,只需要更改原地址的值即可。 所以,a、c都会变
了解以上差异后,可以仔细分析浅拷贝和深拷贝了。
我们都以list为例。
二、浅拷贝
a=“问候”,[ 123,234 ]b=a[:]
打印(b )结果:“问候”,[ 123,234 ]
d=“用于x的标识”
打印(d ) #结果: [ 2126429497672,2126429529480 ]
h=[对于一个人的身份]
打印(h ) #结果: [ 2126428492552,2126428519496 ]
z=[在in b中的标识]
打印(z ) #结果: [ 2126428492552,2126428519496 ]
可以看出d和h的地址不同。 这符合list,是可变的,需要打开不同的空间。 浅拷贝是指拷贝了吗? 如果观察h和z,就会发现a、b中元素的地址是相同的。 如果字符串“hello”的地址一致,则还可以理解,但第二个要素是list地址一致。 这表明了浅拷贝的特征,它只是拷贝了容器中元素的地址。
然后,尝试修改a、b的值。
世界足球锦标赛
a.append (345 )。
打印(' a=',a,'nr ',' b=',b ) )。
# #结果: a=[“世界”,[ 123,234,345 ] ]
# # b=[ '赫鲁',[ 123,234,345 ] ]
的第一个元素str发生了改变,但在b中没有改变; 在a中第二个元素发生变化,在b中也发生变化。 这样一来,对可变对象的修改会打开新的空间,而对可变对象的修改不会打开新的空间。 此外,还证明了浅拷贝只是拷贝了容器中元素的地址。
三、深拷贝
从复制导入复制a=“问候”,[ 123,234 ]
b=深度复制(a ) )。
d=“用于x的标识”
打印(d ) #结果: [ 1507034986248,1507034987528 ]
h=[对于一个人的身份]
打印(h ) #结果: [ 1507032486664,1507034986056 ]
z=[在in b中的标识]
打印(z )结果: [ 1507032486664,1507034987464 ]
如果加深拷贝,就会发现a、b地址和a、b中的要素地址不同。 这就是完全复制的副本。
更改了a的值之后:
世界足球锦标赛
a.append (345 )。
打印(' a=',a,'nr ',' b=',b ) )。
# #结果: a=[“世界”,[ 123,234,345 ] ]
# # b=“问候”,[ 123,234 ]
从结果可以看出,只修正了a,没有修正任何b。 因为b是完整的副本,所以所有元素地址都与a不同,a被修改,b不受影响。