一、内存分配

说到Python的深浅拷贝,就要先说下Python的内存分配

当你为变量赋值时,会先开辟一片内存,存放该值,将变量指向这个值

x = 3

Python 深浅拷贝_浅拷贝

当你将x或3值赋予y时,并不会重新开辟新的内存,而是直接指向之前值3:

# y = 3
y = x

Python 深浅拷贝_浅拷贝_02

你也可以用函数id()来查看地址是相等的:

x = 3
print id(x)
# output 7496216
y = x
print id(y)
# output 7496216

当再次对x赋值为4的时候,会新开辟一片内存,存放4,并且把x重新指向4:

Python 深浅拷贝_浅拷贝_03

地址也变化了不一样了:

x = 3
print id(x)
# output 56189464
y = x
print id(y)
# output 56189464
x = 4
print id(x)
# output 56189440

二、深浅拷贝


深浅拷贝需要引入python的内置模块copy ​​import copy​




对于平常的数值、字符串是没有任何影响的,不管是深拷贝还是浅拷贝都是一样,内存地址不变:

    import copy
x = "test"
print id(x)
# output 53921792
t = x
print id(t)
# output 53921792
y = copy.copy(x)
print id(y)
# output 53921792
z = copy.deepcopy(x)
print id(z)
# output 53921792



针对list时,深拷贝z和浅拷贝y会重新开辟了一片内存地址,但是赋值的t不会重新分配,而是直接指向x的值
Python 深浅拷贝_python深浅拷贝_04

    import copy
x = [2, 3, 5, 8]
print id(x)
# output 48175944
t = x
print id(t)
# output 48175944
y = copy.copy(x)
print id(y)
# output 48231624
z = copy.deepcopy(x)
print id(z)
# output 48174728

当对x内部的元素(非list,dict元素)进行赋新值或修改时,深浅拷贝的值都不会随着x变化而变化,只有赋值类型t随x变化而变化:

    print id(z)
x.append(9)
x[2] = 4
print x
print t
print y
print z
#output
#[2, 3, 4, 8, 9]
#[2, 3, 4, 8, 9]
#[2, 3, 5, 8]
#[2, 3, 5, 8]

当list中存在list时
Python 深浅拷贝_浅拷贝_05

    import copy
a = [1, 10]
x = [2, 3, 5, 8, a]
t = x
y = copy.copy(x)
z = copy.deepcopy(x)
print x
print t
print y
print z
#output
#[2, 3, 5, 8, [1, 10]]
#[2, 3, 5, 8, [1, 10]]
#[2, 3, 5, 8, [1, 10]]
#[2, 3, 5, 8, [1, 10]]

对list中的list进行修改时,你会发现赋值的t和浅拷贝的y会随着List a的改变而改变,而深拷贝不受影响,这是因为浅拷贝只对List x本身进行了拷贝,没有对它内部的List a进行拷贝,只是引用;而深拷贝是对所有对象重新开辟内存,所以不受影响
Python 深浅拷贝_python深浅拷贝_06

    x[4].append(6)
print a
print x
print t
print y
print z
#output
#[1, 10, 6]
#[2, 3, 5, 8, [1, 10, 6]]
#[2, 3, 5, 8, [1, 10, 6]]
#[2, 3, 5, 8, [1, 10, 6]]
#[2, 3, 5, 8, [1, 10]]

对于List来说,浅拷贝等价于如下的赋值:

    import copy
x = [2, 3, 5, 8]
c = x[:] #等价于 c = copy.copy(x)

额外List的小技巧;

    x = [1, 2, 3, 4]
# 从后边加入元素
x[len(x):] = [5, 6, 7]
print(x)
# 从前边增加元素
x[:0] = [-1, 0, 2, 3]
print(x)
# 移除元素
x[1:-1] = []
print(x)
#output
#[1, 2, 3, 4, 5, 6, 7]
#[-1, 0, 2, 3, 1, 2, 3, 4, 5, 6, 7]
#[-1, 7]