龙空技术网

你真的了解Python 中的可变对象和不可变对象

自由坦荡的湖泊AI 24

前言:

目前姐妹们对“python不可变数据结构”大概比较珍视,小伙伴们都需要知道一些“python不可变数据结构”的相关知识。那么小编也在网络上网罗了一些对于“python不可变数据结构””的相关资讯,希望朋友们能喜欢,同学们快快来了解一下吧!

理解可变性和不可变性的概念,特别是在 Python 中可变和不可变的上下文中,对于 Python 编程世界至关重要。这些术语指的是对象被修改时的行为方式。对象是否能够就地更改对于编程效率和数据完整性具有重大影响。

概述

在 Python 中,根据对象的值在创建后是否可以更改,将对象分为可变对象和不可变对象。可变对象可以就地修改,而不可变对象一旦创建就不能更改。理解这两种类型的对象之间的区别对于编写高效且无错误的代码至关重要。

Python 中的可变和不可变

在Python中,术语“可变”和“不可变”是指对象在创建后可以更改的能力。如果对象的状态或值在创建后可以修改,则该对象被认为是可变的。这意味着您可以更改其内部数据或属性,而无需创建新对象。 Python 中可变对象的示例包括列表、字典和集合。如果修改可变对象,对该对象的任何引用都将反映更改。

什么是可变的?

可变是指某些事物是可变的或有能力改变的。在Python中,“可变”是指对象改变其值的能力。这些通常是存储数据集合的对象。

什么是不可变?

不可变是指随着时间的推移不可能发生变化。在Python中,如果一个对象的值不能随时间改变,那么它被称为不可变的。一旦创建,这些对象的价值就是永久的。

可变和不可变对象列表

可变的内置类型对象有:

列表词典用户定义的类(完全取决于用户定义特征)

不可变的内置类型对象有:

数字(整数、有理数、浮点数、小数、复数和布尔值)弦乐元组冷冻集合用户定义的类(完全取决于用户定义特征)

对象可变性是使 Python 成为动态类型语言的特征之一。虽然 Python 中的可变和不可变是一个非常基本的概念,但由于不可变性的不传递性质,它有时可能会有点令人困惑。

Python 中的对象

在Python中,一切都被视为对象。每个对象都具有以下三个属性:

身份——这是指对象在计算机内存中引用的地址。类型——这是指创建的对象的类型。例如 - 整数、列表、字符串等。值——这是指对象存储的值。例如 — List=[1,2,3] 将保存数字 1,2 和 3

虽然 ID 和类型一旦创建就无法更改,但可变对象的值可以更改。

Python 中的可变对象

#创建一个包含印度城市名称的列表

cities = [‘Delhi’, ‘Mumbai’, ‘Kolkata’]

# 打印列表城市中的元素,用逗号和空格分隔

for city in cities:		print(city, end=’, ’)
Output [1]: Delhi, Mumbai, Kolkata

#以十六进制格式打印内存地址中创建的对象的位置

print(hex(id(cities)))
Output [2]: 0x1691d7de8c8

#将新城市添加到城市列表中

cities.append(‘Chennai’)

#打印列表城市中的元素,用逗号和空格分隔

for city in cities:	print(city, end=’, ’)
Output [3]: Delhi, Mumbai, Kolkata, Chennai

#以十六进制格式打印内存地址中创建的对象的位置

print(hex(id(cities)))
Output [4]: 0x1691d7de8c8

上面的示例向我们表明,可以通过向对象“cities”添加一个城市“Chennai”来更改对象“cities”的内部状态,但是该对象的内存地址并没有改变。这证实没有创建新对象,而是同一对象被更改或变异。因此,可以说,引用变量名为“cities”的列表类型的对象是一个可变对象。

现在让讨论术语“不可变”。考虑到我们理解可变代表什么,很明显不可变的定义将包含“NOT”。这是不可变的最简单的定义——内部状态不能改变的对象是不可变的。

#创建一个变量名为“foo”的元组

foo = (1, 2)

#将索引[0]值从1更改为3

foo[0] = 3	TypeError: 'tuple' object does not support item assignment
Python 中的不可变对象

再说一遍,简单的代码将是描述不可变含义的最佳方式。因此,让我们逐步讨论以下代码:

#创建一个包含工作日英文名称的元组

weekdays = ‘Sunday’, ‘Monday’, ‘Tuesday’, ‘Wednesday’, ‘Thursday’, ‘Friday’, ‘Saturday’

# 打印元组工作日的元素

print(weekdays)
Output [1]:  (‘Sunday’, ‘Monday’, ‘Tuesday’, ‘Wednesday’, ‘Thursday’, ‘Friday’, ‘Saturday’)

#以十六进制格式打印内存地址中创建的对象的位置

print(hex(id(weekdays)))
Output [2]: 0x1691cc35090

#tuples 是不可变的,因此您无法添加新元素,因此,使用元组合并与 # + 运算符在元组“weekdays”中添加新的虚构日期

weekdays  +=  ‘Pythonday’,

#打印元组工作日的元素

print(weekdays)
Output [3]: (‘Sunday’, ‘Monday’, ‘Tuesday’, ‘Wednesday’, ‘Thursday’, ‘Friday’, ‘Saturday’, ‘Pythonday’)

#以十六进制格式打印内存地址中创建的对象的位置

print(hex(id(weekdays)))
Output [4]: 0x1691cc8ad68

上面的示例表明,能够使用引用一个对象的相同变量名,该对象是一种包含七个元素的元组类型。然而,新旧元组的ID或内存位置不相同。我们无法更改对象“工作日”的内部状态。 Python 程序管理器在内存地址中创建了一个新对象,变量名称“weekdays”开始引用新对象,其中包含八个元素。因此,我们可以说,引用变量名为“weekdays”的元组类型的对象是一个 IMMUTABLE OBJECT。

在哪里可以使用可变和不可变对象:

可变对象可以用在想要允许任何更新的地方。例如,组织中有一份员工姓名列表,每次雇用新成员时都需要更新该列表。可以创建一个可变列表,并且可以轻松更新它。

不变性为我们在允许并行处理的以网络为中心的环境中执行的不同敏感任务提供了许多有用的应用程序。通过创建不可变对象,您可以密封值并确保没有线程可以调用数据的覆盖/更新。当您想要编写一段无法修改的代码时,这也很有用。例如,尝试查找不可变对象的值的调试代码。

注意事项:不变性的非传递性:

#创建一个元组(不可变对象),其中包含 2 个列表(可变)作为其元素

#元素(列表)包含姓名、年龄和性别

person = (['Ayaan', 5, 'Male'], ['Aaradhya', 8, 'Female'])

#打印元组

print(person)
Output [1]: (['Ayaan', 5, 'Male'], ['Aaradhya', 8, 'Female'])

#以十六进制格式打印内存地址中创建的对象的位置

print(hex(id(person)))
Output [2]: 0x1691ef47f88

#更改第一个元素的年龄。使用索引 [0] 选择元组的第一个元素,然后使用索引 [1] 选择列表的第二个元素,并将年龄的新值指定为 4

person[0][1] = 4

#打印更新后的元组

print(person)
Output [3]: (['Ayaan', 4, 'Male'], ['Aaradhya', 8, 'Female'])

#以十六进制格式打印内存地址中创建的对象的位置

print(hex(id(person)))
Output [4]: 0x1691ef47f88

在上面的代码中,可以看到对象“person”是不可变的,因为它是一种元组类型。但是,它有两个列表作为它的元素,可以更改列表的状态(列表是可变的)。所以,这里没有改变Tuple内部的对象引用,但是引用的对象发生了变异。

同样,探讨一下如果有一个可变对象包含一个不可变对象,它会如何表现?让我们再次使用代码来理解行为——

#创建一个列表(可变对象),其中包含元组(不可变)作为元素

list1 = [(1, 2, 3), (4, 5, 6)]

#打印列表

print(list1)
Output [1]: [(1, 2, 3), (4, 5, 6)]

#以十六进制格式打印内存地址中创建的对象的位置

print(hex(id(list1)))
Output [2]: 0x1691d5b13c8

#改变索引0处的对象引用

list1[0] = (7, 8, 9)

#打印列表

Output [3]: [(7, 8, 9), (4, 5, 6)]

#以十六进制格式打印内存地址中创建的对象的位置

print(hex(id(list1)))
Output [4]: 0x1691d5b13c8

作为个人,希望使用可变和不可变对象的组合创建哪种数据结构,这完全取决于您的要求。

元组的不变性

元组是不可变的,因此一旦在 Python 中创建,就不能对其进行任何更改。这是因为它们支持与字符串相同的序列操作。字符串是不可变的。索引运算符将从元组中选择一个元素,就像在字符串中一样。因此,它们是不可变的。

不变性的例外

与所有情况一样,Python 中的不变性也有例外。并非所有不可变对象都是真正可变的。这会导致你心中产生很多疑问。举个例子来理解这一点。

考虑一个元组“tup”。

现在,如果我们考虑元组tup = ('GreatLearning',[4,3,1,2]) ;

看到元组具有不同数据类型的元素。这里的第一个元素是一个字符串,众所周知,它本质上是不可变的。第二个元素是一个我们都知道是可变的列表。现在,我们都知道元组本身是一种不可变的数据类型。它无法更改其内容。但是,其中的列表可以更改其内容。因此,不可变对象的值不能更改,但其组成对象可以。改变它的值。

标签: #python不可变数据结构