栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

『Python学习笔记』Python中的浅拷贝和深拷贝&可变与不可变类型

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

『Python学习笔记』Python中的浅拷贝和深拷贝&可变与不可变类型

Python中的浅拷贝和深拷贝&可变与不可变类型

文章目录

一. 浅拷贝深拷贝

1.1. 浅拷贝1.2. 深拷贝1.3. 总结 二. Python可变与不可变类型

一. 浅拷贝深拷贝 1.1. 浅拷贝

浅拷贝: 是指重新分配一块内存,创建一个新的对象,里面的元素是原对象中子对象的引用。实现方式1: Python 中也提供了相对应的函数 copy.copy(),适用于任何数据类型实现方式2: 对于可变的序列,我们还可以通过切片操作符':'完成浅拷贝,如list;对于不可变序列,如元组,使用 tuple()或者切片操作符':'不会创建一份浅拷贝,相反,它会返回一个指向相同元组的引用。

常见的浅拷贝的方法,是使用数据类型本身的构造器,比如下面两个例子:

l1 = [1, 2, 3]
l2 = list(l1) # 构造器进行浅拷贝
l2
[1, 2, 3]
l1 == l2
True
l1 is l2
False

s1 = set([1, 2, 3]) # 构造器进行浅拷贝
s2 = set(s1)
s2
{1, 2, 3}
s1 == s2
True
s1 is s2
False
# 我们首先初始化了一个列表 l1,里面的元素是一个列表和一个元组;然后对 l1 执行浅拷贝,赋予 l2。
# 因为浅拷贝里的元素是对原对象元素的引用,因此 l2 中的元素和 l1 指向同一个列表和元组对象。
l1 = [[1, 2], (30, 40)]
l2 = list(l1)

# 接着往下看。l1.append(100),表示对 l1 的列表新增元素 100。这个操作不会对 l2 产生任何影响,
# 因为 l2 和 l1 作为整体是两个不同的对象,并不共享内存地址。操作过后 l2 不变,l1 会发生改变:
l1.append(100) 

# 再来看,l1[0].append(3),这里表示对 l1 中的第一个列表新增元素 3。因为 l2 是 l1 的浅拷贝,
# l2 中的第一个元素和 l1 中的第一个元素,共同指向同一个列表,因此 l2 中的第一个列表也会相对应的
# 新增元素 3。操作后 l1 和 l2 都会改变:
l1[0].append(3)

l1
[[1, 2, 3], (30, 40), 100]

l2
[[1, 2, 3], (30, 40)]
# 最后是l1[1] += (50, 60),因为元组是不可变的,这里表示对 l1 中的第二个元组拼接,
# 然后重新创建了一个新元组作为 l1 中的第二个元素,而 l2 中没有引用新元组,因此 l2 并不受影响。
# 操作后 l2 不变,l1 发生改变:
l1[1] += (50, 60)
l1
[[1, 2, 3], (30, 40, 50, 60), 100]

l2
[[1, 2, 3], (30, 40)]
1.2. 深拷贝

深拷贝: 是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。实现方式1: Python 中以 copy.deepcopy() 来实现对象的深度拷贝。比如上述例子写成下面的形式,就是深度拷贝:

import copy
l1 = [[1, 2], (30, 40)]
l2 = copy.deepcopy(l1)
l1.append(100)
l1[0].append(3)

l1
[[1, 2, 3], (30, 40), 100]

l2 
[[1, 2], (30, 40)]
1.3. 总结

比较操作符'=='表示比较对象间的值是否相等,而'is'表示比较对象的标识是否相等,即它们 是否指向同一个内存地址比较操作符'is'效率优于'==',因为'is'操作符无法被重载,执行'is'操作只是简单的获取对象的 ID,并进行比较;而'=='操作符则会 递归地遍历对象的所有值,并逐一比较浅拷贝中的元素,是原对象中子对象的引用,因此,如果原对象中的元素是可变的,改变其也会影响拷贝后的对象,存在一定的副作用。深度拷贝则会递归地拷贝原对象中的每一个子对象,因此拷贝后的对象和原对象互不相关。另外,深度拷贝中会维护一个字典,记录已经拷贝的对象及其 ID,来提高效率并防止无限递归的发生。

二. Python可变与不可变类型

以下所有的内容 都是基于内存地址 来说的。不可变数据类型: 当该数据类型的对应变量的值发生了改变,那么它对应的内存地址也会发生改变,对于这种数据类型,就称不可变数据类型。可变数据类型:当该数据类型的对应变量的值发生了改变,那么它对应的内存地址不发生改变,对于这种数据类型,就称可变数据类型。

在python中数据类型有:{整型,字符串,元组}不可变,{集合,列表,字典}可变

# 1. 我们可以发现,当数据发生改变后,变量的内存地址发生了改变,那么整型就是不可变数据类型。
a = 1
print(id(a),type(a))
a = 2
print(id(a),type(a))

1912499232 
1912499264 

# 2. 我们可以发现,当数据发生改变后,变量的内存地址发生了改变,那么字符串就是不可变数据类型。
b = 'djx'
print(id(b),type(b))
b = 'djx1996'
print(id(b),type(b))

535056476344 
535056476624 

# 3. 元组被称为只读列表,即数据可以被查询,但不能被修改,但是我们可以在元组的元素中存放一个列表,
#    通过更改列表的值来查看元组是属于可变还是不可变。
# 我们可以发现,虽然元组数据发生改变,但是内存地址没有发生了改变,但是我们不可以以此来判定元组就是可变数
# 据类型。我们回头仔细想想元组的定义就是不可变的。我们修改了元组中列表的值,但是因为列表是可变数据类型,
# 所以虽然在列表中更改了值,但是列表的地址没有改变,列表在元组中的地址的值没有改变,所以也就意味着元组没
# 有发生变化。我们就可以认为元组是不可变数据类型,因为元组是不可变的。
c1 = ['1','2']
c = (1,2,c1)
print(c,id(c),type(c))
c1[1] = 'djx'
print(c,id(c),type(c))

result:
(1, 2, ['1', '2']) 386030735432 
(1, 2, ['1', 'djx']) 386030735432 

# 4. 集合我们常用来进行去重和关系运算,集合是无序的。
#    我们可以发现,虽然集合数据发生改变,但是内存地址没有发生了改变,那么集合就是可变数据类型。

s = {1,'d','34','1',1}
print(s,type(s),id(s))
s.add('djx')
print(s,type(s),id(s))

result:
{'d', 1, '34', '1'}  870405285032
{1, '34', 'djx', '1', 'd'}  870405285032
# 5. 列表是python中的基础数据类型之一,其他语言中也有类似于列表的数据类型,比如js中叫数组,
#    它是以[]括起来,每个元素以逗号隔开,而且它里面可以存放各种数据类型。
# 我们可以发现,虽然列表数据发生改变,但是内存地址没有发生了改变,那么列表就是可变数据类型。
list = [1,'q','qwer',True]
print(list,type(list),id(list))
list.append('djx')
print(list,type(list),id(list))

result:
[1, 'q', 'qwer', True]  808140621128
[1, 'q', 'qwer', True, 'djx']  808140621128


# 6. 字典是python中唯一的映射类型,采用键值对(key-value)的形式存储数据。python对key进行哈希函数
#    运算,根据计算的结果决定value的存储地址,所以字典是无序存储的。但是在3.6版本后,字典开始是有序
#    的,这是新的版本特征。
# 字典的key值可以是整型,字符串,元组,但是不可以是列表,集合,字典。
# 我们可以发现,虽然字典数据发生改变,但是内存地址没有发生了改变,那么字典就是可变数据类型。
tuple = (1)
dic = {1:2}
d = { tuple:1,'key2':'djx','key3':'li'}
print(d,type(d),id(d))
d['key4'] = 'haha'
print(d,type(d),id(d))

result:
{1: 1, 'key2': 'djx', 'key3': 'li'}  256310956320
{1: 1, 'key2': 'djx', 'key3': 'li', 'key4': 'haha'}  256310956320
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/754699.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号