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

Python中的赋值、浅拷贝和深拷贝的区别

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

Python中的赋值、浅拷贝和深拷贝的区别

文章目录
  • 一、变量、可变对象与不可变对象
  • 二、赋值、浅拷贝与深拷贝
    • 2.1 不可变对象的赋值、浅拷贝和深拷贝
    • 2.2 可变对象的赋值、浅拷贝和深拷贝
      • 2.2.1 赋值
      • 2.2.2 浅拷贝
      • 2.2.3 深拷贝
      • 2.2.4 对比总结

一、变量、可变对象与不可变对象

变量指向一个对象,而对象有可变与不可变之分

>>> a = "HELLO"
>>> id(a)
140182492168632
>>> a = "hello"
>>> id(a)
140182492168688
>>> a = ["hello_1", "hello_2"]
>>> id(a)
140182492190088
>>> a.append("hello_3")
>>> id(a)   #当可变对象的内容改变时,指向它的变量保存的地址不变
140182492190088

可变对象与不可变对象

>>> L = ['hello_2', 'hello_3', 'hello_1']
>>> print(sorted(L))    #sorted()函数不改变传入的参数本身
['hello_1', 'hello_2', 'hello_3']
>>> print(L)
['hello_2', 'hello_3', 'hello_1']
>>> L.sort()    #List的成员函数sort()会改变自己
>>> print(L)
['hello_1', 'hello_2', 'hello_3']

>>> s = 'hello'
>>> print(s.replace('h', 'H'))  #因为str是不可变数据类型,所以会返回一个新字符串
Hello
>>> print(s)
hello

务必搞清楚,改变的是对象本身,还是仅得到了一个中间结果

注意:

  • 变量无类型,对象有类型
  • 对象是内存中存储数据的实体,变量则是指向对象的指针(当指向的对象可变时,可以用这个变量来修改对象本身;指向的对象不可变时,修改变量会让变量指向一个新对象)

*总结:

  1. 不可变对象:对象所指向的内存中的值不能被改变,当改变这个变量的时候,原来指向的内存中的值不变,变量不再指向原来的值,而是开辟一块新的内存,变量指向新的内存。
  2. 可变对象:对象指向的内存中的值会改变,当更改这个变量的时候,还是指向原来内存中的值,并且在原来的内存值进行原地修改,并没有开辟新的内存。
  3. 在Python中,数值类型int、float、字符串str、元祖tuple、bool都是不可变对象;列表list、集合set、字典dict都是可变对象
二、赋值、浅拷贝与深拷贝 2.1 不可变对象的赋值、浅拷贝和深拷贝
import copy
a=(1,2,3)

print("=====赋值=====")
b=a
print(a)
print(b)
print(id(a))
print(id(b))

print("=====浅拷贝=====")
b=copy.copy(a)
print(a)
print(b)
print(id(a))
print(id(b))

print("=====深拷贝=====")
b=copy.deepcopy(a)
print(a)
print(b)
print(id(a))
print(id(b))

结果:

=====赋值=====
(1, 2, 3)
(1, 2, 3)
43481128
43481128
=====浅拷贝=====
(1, 2, 3)
(1, 2, 3)
43481128
43481128
=====深拷贝=====
(1, 2, 3)
(1, 2, 3)
43481128
43481128

因此可以看到,对于不可变对象的无论是赋值、浅拷贝还是深拷贝,都没有创建新的对象空间,而是指向的原对象地址。

2.2 可变对象的赋值、浅拷贝和深拷贝 2.2.1 赋值

可变类型对象的赋值,传递的是引用,类似于C语言中的指针

>>> a
['hello_1', 'hello_2', 'hello_3']
>>> id(a)
140182492190088
>>> b = a   #对于可变对象变量的赋值,改变其中一个变量对象的内容,都会影响另一个变量对象,因为他们指向的是同一个对象
>>> id(b)
140182492190088
>>> a.append("hello_4")
>>> a[0] = "hello_5"
>>> a
['hello_5', 'hello_2', 'hello_3', 'hello_4']
>>> b
['hello_5', 'hello_2', 'hello_3', 'hello_4']
>>> id(a) == id(b)
True
2.2.2 浅拷贝

浅拷贝有三种形式: 切片操作,工厂函数,copy模块中的copy函数。
浅拷贝只拷贝父对象,不会拷贝对象的内部的子对象

import copy

lst = [1,2,[3,4]]

# 切片操作
lst1 = lst[:]
lst1 = [each for each in lst]

# 工厂函数
lst1 = list(lst)

# copy函数
lst1 = copy.copy(lst)
2.2.3 深拷贝

深拷贝完全拷贝了父对象及其子对象,具体通过copy 模块的 deepcopy 方法实现

>>>import copy
>>> c = copy.deepcopy(a)
>>> a, c
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
>>> a[1].append(5)
>>> a, c
({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4]})
2.2.4 对比总结
import copy

a = [[1, 2, 3], [4, 5, 6]]
b = a   #此处的b类似于别名
c = copy.copy(a)
d = copy.deepcopy(a)

a.append(7)
a[1][2] = 10

print('原数组: ', a)
print('引用赋值: ', b)
print('浅拷贝: ', c)
print('深拷贝: ', d)

结果为:

原数组: [[1, 2, 3], [4, 5, 10], 7]
引用赋值: [[1, 2, 3], [4, 5, 10], 7]
浅拷贝: [[1, 2, 3], [4, 5, 10]]
深拷贝: [[1, 2, 3], [4, 5, 6]] 

总结:

  • 赋值就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。
  • 浅拷贝是创建一个新的对象,但它包含的是对原始对象中所有元素项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变):
    • 完全切片方法;
    • 工厂函数,如list();
    • copy模块的copy()函数}。
  • 深拷贝创建一个新的对象,并且递归的复制它所包含的对象(修改其中一个,另外一个不会改变):
    • copy模块的deep.deepcopy()函数
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/339129.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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