不可变数据结构是指一旦创建后就不能更改的数据结构。这意味着任何尝试修改数据结构的操作都会导致创建一个新的实例而不是改变原始实例。不可变数据结构对于确保数据在整个程序执行过程中保持不变非常有用,这可以帮助防止错误并使代码更容易理解和维护。
在深入探讨这个话题之前,让我们快速回顾一下什么是数据结构?数据结构是专门用于组织、处理、检索和存储数据的格式。它们定义了数据如何在内存中排列以及如何有效地执行访问、插入、删除和更新等操作。
Python 中的不同不可变数据结构
不可变数据结构因其稳定性、线程安全性和易用性而在 Python 中至关重要。以下是 Python 中的不同不可变数据结构:
元组(Tuples)
元组是在创建后不能更改的有序元素集合。它们可以包含混合的数据类型,并且对于表示固定集合的相关项很有用。
创建元组
元组使用括号 ()
创建,元素之间用逗号 ,
分隔。即使是单个元素的元组也需要一个尾随逗号以区分其与组合表达式。
empty_tuple = ()
single_element_tuple = (5,)
print("单元素元组:", single_element_tuple)
multi_element_tuple = (1, 2, 'Tutorialspoint', 3.14)
print("多元素元组:", multi_element_tuple)
nested_tuple = (1, (2, 3), 'Learning')
print("嵌套元组:", nested_tuple)
输出
单元素元组: (5,)
多元素元组: (1, 2, 'Tutorialspoint', 3.14)
嵌套元组: (1, (2, 3), 'Learning')
理解 Python 中的元组不可变性
下面我们将通过一个例子来理解 Python 中元组的不可变性。
my_tuple = (1, 2, 3, 'hello')
try:
my_tuple[0] = 10
except TypeError as e:
print(f"错误: {e}")
try:
my_tuple.append(4)
except AttributeError as e:
print(f"错误: {e}")
try:
my_tuple = (4, 5, 6)
except TypeError as e:
print(f"错误: {e}")
print("原始元组:", my_tuple)
输出
错误: 'tuple' 对象不支持项赋值
错误: 'tuple' 对象没有属性 'append'
原始元组: (4, 5, 6)
字符串(Strings)
字符串是在 Python 中用于表示和操作文本数据的字符序列。它们被包含在单引号 '
或双引号 "
内,也可以使用三引号 """
来创建多行字符串。
关键特性
字符串是 Python 中的基础,在诸如文本处理、输入/输出操作和应用程序中的数据表示等任务中提供了一套灵活的内置方法,用于有效操纵和格式化文本信息。
创建字符串
每种类型的字符串创建方法(', ", """)都有其特定的用途,取决于我们需要在字符串中包含引号、处理多行文本还是其他特定格式要求。
single_quoted_string = 'Hello, Welcome to Tutorialspoint'
double_quoted_string = "Python Programming"
multi_line_string = """This is a
multi-line
string"""
print(single_quoted_string)
print(double_quoted_string)
print(multi_line_string)
输出
Hello, Welcome to Tutorialspoint
Python Programming
This is a
multi-line
string
理解 Python 中的字符串不可变性
下面通过一个例子来理解 Python 中字符串的不可变性。
my_string = "Hello"
modified_string = my_string + " Learners"
print(modified_string)
print(my_string)
try:
my_string[0] = 'h'
except TypeError as e:
print(f"错误: {e}")
输出
Hello Learners
Hello
错误: 'str' 对象不支持项赋值
不可变集合(Frozen Sets)
Python 中的不可变集合(frozenset)是集合的不可变版本。一旦创建后,它的元素就不能更改、添加或移除。不可变集合特别适用于我们需要一个在整个程序执行过程中保持恒定的集合的情况,特别是在我们希望将其作为字典中的键或另一个集合中的元素时。
创建不可变集合
我们可以使用 frozenset() 构造函数通过传递一个可迭代对象(如列表或其他集合)作为参数来创建一个不可变集合。
fset = frozenset([1, 2, 3, 4])
print(fset)
输出
frozenset({1, 2, 3, 4})
理解 Python 中的不可变集合
下面的例子展示了 frozensets 在创建后是不可变的,并且不允许修改。
frozen_set = frozenset([1, 2, 3, 4])
try:
frozen_set.add(5)
except AttributeError as e:
print(f"错误: {e}")
try:
frozen_set.remove(2)
except AttributeError as e:
print(f"错误: {e}")
print("原始 frozenset:", frozen_set)
输出
错误: 'frozenset' 对象没有属性 'add'
错误: 'frozenset' 对象没有属性 'remove'
原始 frozenset: frozenset({1, 2, 3, 4})
命名元组(Named Tuples)
命名元组是一种轻量级的数据结构,可在 Python 的 collections 模块中找到,它表现得像元组一样,但允许我们通过名称和索引来访问其元素。
它结合了元组的优点,如不可变性、内存效率高,并且能够通过名称引用元素,增强了代码的可读性和可维护性。
创建命名元组
我们可以使用 collections 模块中的 namedtuple 工厂函数定义命名元组。它接受两个参数:命名元组类型的名称以及指定其字段名称的字符串或可迭代对象。
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p1 = Point(1, 2)
print(p1[0])
print(p1.x)
print(p1.y)
输出
1
1
2
理解 Python 中的命名元组不可变性
Python 中的命名元组是由 collections.namedtuple 工厂函数提供的,确实是不可变的。它们的行为类似于常规元组,但通过使其更加易读和自我记录来增强可读性和可维护性。
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(x=1, y=2)
print(p)
try:
p.x = 10
except AttributeError as e:
print(f"发生错误: {e}")
print(p.x)
print(p.y)
输出
Point(x=1, y=2)
发生错误: can't set attribute
1
2