1、可变类型与不可变类型

在Python中,数据类型可以分为可变类型(Mutable)和不可变类型(Immutable)。这指的是对象在创建后是否可以更改其值或状态。

  • 不可变类型是指创建后不能更改其值或状态的对象。如果对不可变类型的对象进行修改,将会创建一个新的对象,原始对象的值保持不变。在修改后,对象的身份标识(即内存地址)会发生变化。

Python中常见的不可变类型:

整数(Integer)

浮点数(Float)

布尔值(Boolean)

字符串(String)

元组(Tuple)

  • 可变类型是指可以在原地修改的对象,即可以改变其值或状态。当对可变类型的对象进行修改时,不会创建新的对象,而是直接修改原始对象。在修改后,对象的身份标识(即内存地址)保持不变。

Python中常见的可变类型:

列表(List)

字典(Dictionary)

集合(set)

  • 对于可变类型,可以通过方法调用或索引赋值进行修改,而不会改变对象的身份标识。而对于不可变类型,任何修改操作都会创建一个新的对象。

图中x=1与x=2时,id值不相等,也就说明所在的内存地址不一样,只是程序应用时,会将变量指向到该内存块,正如当y也赋值2时,id值与x=2时的id值一样;而z赋值于列表时,由于列表是可变类型,所以追加了元素后其id也不变。。

Python列表的深浅拷贝_浅拷贝

2、数据类型的变量传递

  • 不可变类型变量传递
x= 1
y = x
print(id(x))
print(id(y))	#此时x和y的id()值一样
  • 1.
  • 2.
  • 3.
  • 4.

Python列表的深浅拷贝_不可变类型_02

x= 2
print(id(x))	#x的id()发生变化
print(id(y))	#y的id()还是与之前保持一致
  • 1.
  • 2.
  • 3.

Python列表的深浅拷贝_深拷贝_03

  • 可变类型变量传递

变量实际上是对对象的引用。变量传递的核心是两个变量引用同一地址空间。

列表传递后,当原列表l1发生改变,l2列表也随之变化,且在整个过程中,id()值没有发生变化。列表赋值给变量后,变量之间的数据有共享属性。

Python列表的深浅拷贝_浅拷贝_04

当l1作为列表元素被包含到l2中,l1与l2的id值不相同;当l2移除元素后再被l1扩展后,其列表在表明上与l3的一样,但实际上l1与l3各自的id并不一致。

Python列表的深浅拷贝_可变类型_05

  • 可变类型与不可变类型变量传递

列表l1与l2共享同一列表,当l1赋值给可变类型数据后,l2并没有随着l1的变化发生改变。

Python列表的深浅拷贝_Python_06

l1作为列表元素被l2包含,当l1变为可变类型数据后,l2不变。当l1再次赋值不可变数值后,l2依旧不变。列表中的元素保留的是原列表所在内存地址,而不是等号前的变量名称。

Python列表的深浅拷贝_浅拷贝_07

同理,若l2对第一个元素进行修改,由于l1与l2[0]的内存地址不冲突,所以l1也不会受影响。

Python列表的深浅拷贝_深拷贝_08

  • 总结
变量variable= 值value
  • 1.

变量传递实际上需要盯的是:值value的内存地址是否发生变化。

可变类型数据:值value(比如列表)随着内部元素的改变,该列表所在内存地址空间不会发生变化。若创建一个新的“variable = value”并且是同样的列表,会开辟一个新的内存地址空间。

不可变类型数据:值value(比如字符)占据唯一内存地址空间,若创建一个新的“variable = value”并且是同样的字符,变量variable会指向唯一的内存地址空间。

3、列表的深浅拷贝

在Python中,列表的拷贝可以分为深拷贝和浅拷贝两种方式。

  • 浅拷贝

浅拷贝(Shallow Copy)是创建一个新的列表对象,该对象与原始列表共享相同的元素对象。当你对其中一个列表进行修改时,另一个列表也会受到影响。

#浅拷贝三种方法
l1 = [1,2,3]

#方法一:使用切片进行拷贝
l2 = l1[:]
#方法二:使用list()函数
l2 = list(l1)
#方法三:使用copy()函数
l2 = l1.copy()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

通过浅拷贝的列表,虽然列表的id不同,但其内部的元素id是一样的。

Python列表的深浅拷贝_不可变类型_09

而我们又知道,可变类型数据传递变量后id会变,而不可变类型数据传递变量后id不会变,所以可得出下列结论:列表内部的可变类型数据元素的改变,不会影响到浅复制的列表;而列表内部的不可变类型元素的改变,影响到浅复制的列表。

Python列表的深浅拷贝_Python_10

如果想让复制的列表里无论什么类型数据都与原列表具备独立性、没有关联性,可以使用深拷贝。

  • 深拷贝(Deep Copy)是创建一个新的列表对象,并且递归地复制原始列表中的所有元素对象。这意味着原始列表和深拷贝的列表是完全独立的,对其中一个列表的修改不会影响另一个列表。

可以使用copy()模块中的deepcopy()函数进行深拷贝:

import copy

original_list = [1, 2, 3, 4, 5]
deep_copy = copy.deepcopy(original_list)
  • 1.
  • 2.
  • 3.
  • 4.

需要注意的是,深拷贝可能会更耗费内存和时间,特别是当拷贝的列表中包含大量嵌套的对象时。

Python列表的深浅拷贝_不可变类型_11

copy.copy()		#浅拷贝
copy.deepcopy()	#深拷贝
  • 1.
  • 2.