python字符串赋值与java区别_Python赋值、浅拷贝和深拷贝的区别?

写在前面:对于非容器类型,如数字、字符,以及其他的“原子”类型,没有拷贝一说,产生的都是原对象的引用。

一、赋值(assignment)

在Python中,用一个变量给另一个变量赋值,其实就是给当前内存中的对象增加一个“标签”而已,这两个变量指向的是同一片内存。

a = [1,2,3]

b = a

print(id(a),id(b))

>>>60742472 60742472

注意:浅拷贝和深拷贝的不同仅仅是对组合对象来说,所谓的组合对象就是包含了其它对象的对象,如列表,类实例。而对于数字、字符串以及其它“原子”类型,没有拷贝一说,产生的都是原对象的引用。

二、浅拷贝(shallow copy)

浅拷贝会创建新对象,其内容非原对象本身的引用,而是原对象内第一层对象的引用。(拷贝组合对象,不拷贝子对象)

常见的浅拷贝有:切片操作、工厂函数、对象的copy()方法、copy模块中的copy函数。工厂函数:一个函数,可以生产出属性相同的对象;实际不是函数,而是一个类对象,返回都是类的实例。

a = [1,2,3]

# 工厂函数

b = list(a)

print(id(a),id(b))

>>> 60730760 60091784

# 切片操作

b = a[ : ]

print(id(a),id(b))

>>> 60730760 60731016

b = [ x for x in a ]

print(id(a),id(b))

>>> 60730760 60091784

# copy模块中的copy函数

b = copy.copy(a)

print(id(a),id(b))

>>> 60730760 60731016

浅拷贝产生的列表b不再是列表a了,使用is判断可以发现他们不是同一个对象,使用id查看,他们也不指向同一片内存空间。但是当我们使用id(x) for x in a 和 id(x) for x in b来查看a和b 中元素的地址时,可以看到二者包含的元素的地址是相同的。

在这种情况下,列表a和b是不同的对象,修改列表b理论上不会影响到列表a。

但是要注意的是,浅拷贝之所以称之为浅拷贝,是它仅仅只拷贝了一层,在列表a中有一个嵌套的list,如果我们修改了它,情况就不一样了。

a = [1,2,3,['python']]

b = list(a)

print(id(a),id(b))

>>> 60758728 60090888

for x,y in zip(a,b):

print(id(x),id(y))

>>>

8791184094032 8791184094032

8791184094064 8791184094064

8791184094096 8791184094096

60758472 60758472

a[3].append('java')

print(a,b,id(a),id(b))

>>> [1, 2, 3, ['python', 'java']] [1, 2, 3, ['python', 'java']] 60758728 60090888

比如:a[3].append(‘java’)。查看列表b,会发现列表b也发生了变化,这是因为,我们修改了嵌套的list,修改外层元素,会修改它的引用,让它们指向别的位置,修改嵌套列表中的元素,列表的地址并未发生变化,指向的都是用一个位置。

三、深拷贝(deep copy)

深拷贝只有一种方式:copy模块中的deepcopy函数。

所谓“深拷贝”,是指创建一个新的对象,然后递归的拷贝原对象所包含的子对象。因此,它的时间和空间开销要高。深拷贝出来的对象与原对象没有任何关联。

import copy

a = [1, 2, 3]

b = copy.deepcopy(a)

print(id(a), id(b))

>>> 60742344 60742600

for x, y in zip(a, b):

print(id(x), id(y))

>>>

8791184094032 8791184094032

8791184094064 8791184094064

8791184094096 8791184094096

看了上面的例子,有人可能会疑惑:

为什么使用了深拷贝,a和b中元素的id还是一样呢?

答:这是因为对于不可变对象,当需要一个新的对象时,python可能会返回已经存在的某个类型和值都一致的对象的引用。而且这种机制并不会影响 a 和 b 的相互独立性,因为当两个元素指向同一个不可变对象时,对其中一个赋值不会影响另外一个。

我们可以用一个包含可变对象的列表来确切地展示“浅拷贝”与“深拷贝”的区别:

import copy

a = [[1, 2, 3],[0,0]]

b = copy.copy(a) #浅拷贝得b

c = copy.deepcopy(a) #深拷贝得c

print(id(a), id(b)) #a和b不同

>>> 60722504 60772424

for x, y in zip(a, b):

print(id(x), id(y)) #a和b的子对象相同

>>>

60723016 60723016

60772488 60772488

print(id(a), id(c)) #a和c不同

>>> 60722504 61671240

for x, y in zip(a, c):

print(id(x), id(y)) #a和c的子对象不同

>>>

60723016 61671496

60772488 61671432

从这个例子中可以清晰地看出浅拷贝与深拷贝地区别。

载于《python之基础知识大全》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值