Python 可变与不可变数据类型

2024年8月29日 | 阅读 7 分钟

Python 中的可变和不可变数据类型

可变或不可变是描述数据类型在初始化后是否可更新的常用词。基本解释如下:可变对象是其内部状态可以更改的对象。相反,一旦在 Python 中创建了一个不可变对象,我们就无法以任何方式更改它。

什么是可变数据类型?

当任何东西可以被修改或更改时,它就被称为可变的。Python 中的“可变”一词指的是对象修改其值的能力。这些通常是保存数据集合的东西。

什么是不可变数据类型?

不可变是指一个状态,在这个状态下不会随时间发生任何变化。如果我们在 Python 中无法随时间更改对象的值,则该对象被认为是不可变的。一旦创建,这些 Python 对象的值就是固定的。

可变和不可变对象的列表

Python 可变数据类型

  • 列表
  • 字典
  • 集合 (Sets)
  • 用户定义类(取决于用户如何定义类的特性)

Python 不可变数据类型

  • 数字(整数、浮点数、复数、小数、有理数和布尔值)
  • 元组 (Tuples)
  • 字符串
  • 冻结集合

Python id() 函数

当您定义一个 Python 对象时,程序会为其分配一段内存。每个 Python 对象都有一个唯一的地址,它告诉应用程序该对象在内存中的位置。

Python 中的每个对象都有一个与对象内存地址相关联的唯一 ID。使用内置的 Python id() 函数可以读取这个特殊的 ID。

例如,让我们读取一个示例字符串对象在内存中的位置

代码

输出

140452604995952

Python 中的可变性

正如我们已经说过的,不可变的 Python 对象是无法更改的。

在 Python 中,整数数据类型是不可变对象或数据类型的典型示例。让我们进行一个简单的实验来理解这一点。

首先,让我们创建两个整数变量 x 和 y。变量 y 是变量 x 的引用

现在,x 和 y 都指向内存中的同一位置。换句话说,两个整数变量都应该返回相同的 ID(通过 id() 函数)。让我们确认一下

代码

输出

x and y have same id:  True

因此,变量 x 和 y 指向一个整数对象。换句话说,即使只有一个整数对象,两个变量也指向它。

现在让我们更改 x 的值。接下来,我们再次比较 x 和 y 的引用 ID

代码

输出

x and y have the same ids: False

这是因为 x 现在指向一个不同的整数对象。因此,整数 3 本身保持不变。但是,变量 x,它之前引用了它,现在指向新的整数实体 13。

因此,即使我们似乎修改了原始整数变量,但实际上并没有。在 Python 中,整数对象是不可变数据类型,这意味着一旦创建,就无法更改整数对象。

让我们再次使用可变对象进行类似的测试。

例如,创建一个列表,并将其放入第二个变量中。然后,比较两个列表的引用 ID。然后,让我们对创建的列表进行一些更改。然后,让我们看看两个列表的引用 ID 是否仍然一致

代码

输出

Both list variables have the same ids:  True
Both list variables have the same ids:  True

此外,它们的引用 ID 匹配。因此,列表对象 num 和 l 指向内存位置。这表明我们可以通过添加另一个元素来显式更改列表对象。因此,列表数据结构必须是可变的。Python 列表就是这样工作的。

Python 中可变对象的示例

列表

由于列表的可变性,我们可以通过赋值运算符或索引运算符来更改其内容。

让我们来看一个例子。

代码

输出

The original list:  ['Python', 'Java', 23, False, 5.3]
The modified list:  ['Python', 'Java', 'changed', False, 5.3]

字典

由于字典的可变性,我们可以通过实现内置的 update 函数或使用键作为索引来修改它们。

让我们来看一个例子。

代码

输出

The original dictionary:  {1: 'a', 2: 'b', 3: 'c'}
The modified dictionary:  {1: 'a', 2: 'changed', 3: 'c'}

Set

由于集合的可变性,我们可以使用内置函数(update)来修改它们。

看一个例子

代码

输出

The original set:  {1, 2, 3, 4}
The modified set:  {1, 2, 3, 4, 'b', 'a', 'c'}

不可变 Python 对象示例

int

由于 Python 中的 int 是不可变数据类型,我们无法更改或更新它。

正如我们之前学到的,不可变对象在更新时会改变它们的内存地址。

这是例子

代码

输出

The memory address of int before updating:  11531680
The memory address of int after updating:  11532000

float

由于 Python 中的 float 对象是不可变数据类型,我们无法更改或更新它。正如我们之前学到的,不可变对象在更新时会改变它们的内存地址。

这是例子

代码

输出

The memory address of float before updating:  139992739659504
The memory address of float after updating:  139992740128048

String

由于 Python 中的字符串是不可变的,我们无法添加或编辑任何数据。当我们尝试修改字符串的任何部分时,我们会收到警告,提示字符串是不可变的。

这是例子

代码

输出

TypeError                                 Traceback (most recent call last)
<ipython-input-3-4e0fff91061f> in <module>
      3 string = 'hello peeps'
      4 
----> 5 string[0] = 'X'
      6 
      7 print(string)

TypeError: 'str' object does not support item assignment

元组

由于 Python 中的元组本质上是不可变的,因此我们无法添加或修改其任何内容。这是例子

代码

输出

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-e011ebc4971e> in <module>
      5 
      6 # Trying to modify the tuple object
----> 7 tuple_[0] = 'X'
      8 print(tulple_)
      9 

TypeError: 'tuple' object does not support item assignment

冻结集合

与集合类似,冻结集合也是不可变的数据结构。虽然集合的元素可以随时更改,但冻结集合不能。因此,无法向 frozenset 添加或更新任何内容。

这是例子

代码

输出

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-2cafcda94faf> in <module>
      6 
      7 # Updating the value of the frozenset
----> 8 fset[1] = 76
      9 print(fset)
     10 

TypeError: 'frozenset' object does not support item assignment