'is'和'=='的区别 | 深、浅拷贝

1.is和==的区别

Python中的对象包含三要素id、type、value。

1.id
在内存中存储的位置,用来唯一标识一个对象

-id(变量名)查看id

2.type

标识对象的类型

type(变量名)查看数据类型

3.value

is判断的是a对象是否就是b对象,是通过type,value,id三者同时来判断的。


==判断的是a对象的值是否和b对象的值相等,是通过value,type来判断的。

换句话说:

1)若a  is   b=====>True,则a==b一定相等,返回True;
2)若a==b ====> True, a is b 不一定;

a=3
b=a
print(id(a),id(b))
print(type(a),type(b))
print(a,b)
print(a is b)
print(a==b)

a=[3,4,5]
b=a.copy()
print(id(a),id(b))
print(type(a),type(b))
print(a,b)
print(a is b)
print(a==b)

2.深拷贝和浅拷贝

1.定义:

在Python中对象的赋值其实就是对象的引用。当创建一个对象,把它赋值给另一个变量的时候,python并没有拷贝这个对象,只是拷贝了这个对象的引用而已。

浅拷贝:拷贝了最外围的对象本身,内部的元素都只是拷贝了一个引用而已。也就是,把对象复制一遍,但是该对象中引用的其他对象不复制

深拷贝:外围和内部元素都进行了拷贝对象本身,而不是引用。也就是,把对象复制一遍,并且该对象中引用的其他对象我也复制。

2.应用的范围:

1,切片可以应用于:列表、元组、字符串,但不能应用于字典。
2,深浅拷贝,既可应用序列(列表、元组、字符串),也可应用字典。

3.深浅拷贝的作用:

1,减少内存的使用
2,以后在做数据的清洗、修改或者入库的时候,对原数据进行复制一份,以防数据修改之后,找不到原数据。

####对于不可变对象的深浅拷贝:

不可变对象类型,没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已。一句话就是,不可变类型,不管是深拷贝还是浅拷贝,地址值和拷贝后的值都是一样的。

 1.浅拷贝:

1)直接赋值(li1 = li): 只传递对象的引用, li1指向对象li的内存地址空间,  因此, 原有列表li改变, 被赋值的li1也会做相应的改变

2)li2=li.copy()):li和li2的内存地址不同,因此原始数据改变 , 子对象不改变.

li2=li[:]

2.深拷贝:

import copy

li3=copy.deepcopy(li))

li和li3的内存地址不同,包含子对象的拷贝, 所以原始对象改变并不会造成深拷贝里面任何子项的改变.

####对于可变对象的深浅拷贝:

=浅拷贝:值相等,地址相等
copy浅拷贝:值相等,地址不相等
deepcopy深拷贝:值相等,变量地址不同,但子对象地址相等

import copy
a=[1,2,3,4]
#a.append(5)
b1=a
b2=a[:]
b3=a.copy()
b4=copy.deepcopy(a)
print(a,b2,b3,b1,b4)
print(id(b1),id(b2),id(b3),id(a),id(b4))
print(id(b2[0]),id(b3[0]))


***面试常问:请简述赋值, 深拷贝和浅拷贝的区别?(python中如何拷贝一个对象?)

- 直接赋值(li1 = li): 只传递对象的引用, li1指向对象li的内存地址空间,
    因此, 原有列表li改变, 被赋值的li1也会做相应的改变.

- 浅拷贝(三种实现方式 eg: li2=li.copy()):li和li2的内存地址不同,
    但是子对象的内存地址相同, 因此,原始数据改变 , 子对象也改变.

- 深拷贝(import copy, eg: li3=copy.deepcopy(li)), li和li3的内存地址不同,
         包含子对象的拷贝, 所以原始对象改变并不会造成深拷贝里面任何子项的改变.

*** 当深拷贝和浅拷贝, 针对的对象全部是不可变数据类型时, 两者效果相同;
*** 当深拷贝和浅拷贝, 针对的对象包含是可变数据类型时, 两者才有上述区别;

猜你喜欢

转载自blog.csdn.net/forever_wen/article/details/81634786