侧边栏壁纸
博主头像
张种恩的技术小栈博主等级

行动起来,活在当下

  • 累计撰写 747 篇文章
  • 累计创建 65 个标签
  • 累计收到 39 条评论

目 录CONTENT

文章目录

Python基础(8)之深浅拷贝

zze
zze
2019-02-21 / 0 评论 / 0 点赞 / 673 阅读 / 3581 字

不定期更新相关视频,抖音点击左上角加号后扫一扫右方侧边栏二维码关注我~正在更新《Shell其实很简单》系列

在 Python 中,字符串(str)、元组(tuple)和数字(Number)是不可更改的对象,而列表(list)、字典(dict)等则是可以修改的对象。

  • 不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a
  • 可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身 la 没有动,只是其内部的一部分值被修改了。

Python 函数的参数传递:

  • 不可变类型:类似 c++ 的值传递,如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。比如在 fun(a) 内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身;
  • 可变类型:类似 c++ 的引用传递,如列表、字典、集合。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响;

Python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
而深浅拷贝其实主要是针对可变对象来说的,先看如下示例:

lst1 = [1,2,3]
lst2 = lst1
lst2.append(4)
print(lst1 is lst2)
print(lst1)
'''
True
[1, 2, 3, 4]
'''

由于 lst2 = lst1lst2 指向了 lst1 指向的地址,所以对 lst2 的操作实际上就是对 lst1 的操作。
如果我们希望 lst2 独立出来,让其和 lst1 指向不同的地址,此时就需要使用拷贝操作了。

copy 浅拷贝

要使用拷贝操作需要使用到 copy 模块,看下面示例:

from copy import *
lst1 = [1,2,3]
lst2 = copy(lst1)
lst2.append(4)
print(lst1 is lst2)
print(lst1)
print(lst2)

'''
False
[1, 2, 3]
[1, 2, 3, 4]
'''

可以看到,通过 copy 函数对 lst1 进行了拷贝,然后将返回值赋值给了 lst2,随后对 lst2 的操作就没有影响到 lst1 了,因为此时 lst2lst1 指向内存中的地址已经不同了。
我们再看一个示例:

from copy import *

lst1 = [1, 2, 3, ['a', 'b', 'c']]
lst2 = copy(lst1)
lst2[-1].append('d')
print(lst1 is lst2)
print(lst1[-1] is lst2[-1])
print(lst1)
print(lst2)

'''
False
True
[1, 2, 3, ['a', 'b', 'c', 'd']]
[1, 2, 3, ['a', 'b', 'c', 'd']]
'''

可以看到,我们依旧使用 copy 函数对 lst1 进行了拷贝,此时的 lst1 和之前不一样的是里层还有一个嵌套的列表,我们对 lst1 里层列表和 lst2 里层列表进行操作发现 lst1lst2 虽然指向内存中不同的地址,但是 lst1 内层的列表和 lst2 内层的列表指向的地址还是相同的,即通过 copy 函数拷贝仅仅是对列表最外层元素进行了拷贝,所以它就叫浅拷贝。

deepcopy 深拷贝

如果我们希望拷贝时能将内层元素一同拷贝,此时就需要使用 copy 模块中的 deepcopy 函数了,也就是深拷贝,看如下示例:

from copy import *

lst1 = [1, 2, 3, ['a', 'b', 'c']]
lst2 = deepcopy(lst1)
lst2[-1].append('d')
print(lst1 is lst2)
print(lst1[-1] is lst2[-1])
print(lst1)
print(lst2)

'''
False
False
[1, 2, 3, ['a', 'b', 'c']]
[1, 2, 3, ['a', 'b', 'c', 'd']]
'''

特殊的元组

最外层为元组

上述深浅拷贝操作对 set 集合、list 列表、dict 字典都有效,有差异的就是元组了,看如下示例:

from copy import *

tup1 = (1, 2, 3, ['a', 'b', 'c'])
tup2 = copy(tup1)
print(tup1 is tup2)

‘’‘
True
’‘’

可以看到上述操作对 tup1 进行了浅拷贝并将返回值赋值给了 tup2,但是最后发现它们依旧指向同一个地址,即浅拷贝在最外层是元组时是无效的,那么深拷贝呢?

from copy import *

tup1 = (1, 2, 3, ['a', 'b', 'c'])
tup2 = deepcopy(tup1)
print(tup1 is tup2)

‘’‘
True
’‘’

经过测试发现,深浅拷贝在最外层为元组时都无效。

内层的元组

最外层是元组时深浅拷贝是失效的,那么如果元组在列表或字典、集合内层的时候,是否能拷贝成功呢?
元组在内层,浅拷贝只能拷贝最外层,所以肯定是没戏了,那么下面来看下深拷贝能否拷贝内层元组的元素。

from copy import *

lst1 = [1, 2, 3, ('a', 'b', 'c')]
lst2 = deepcopy(lst1)
print(lst1 is lst2)
print(lst1[-1] is lst2[-1])

'''
False
True
'''

从结果可以看出深拷贝是可以拷贝内层元组的。

0

评论区