深入探究:Python元组与列表的对比分析
本指南将带您深入了解Python中元组和列表的相似之处与差异。此外,您将了解在何种情境下应优先考虑使用元组。
列表和元组是Python中两种基本的数据结构,它们都可以用来存储一系列元素。
尽管元组和列表在支持索引、切片以及容纳多种数据类型等方面具有相似的功能,理解它们之间的差异对于选择合适的数据结构至关重要。
让我们开始探索吧。
👩🏽💻 您可以启动Python交互式解释器(REPL)并跟随本教程进行操作。或者,您也可以使用在线Python编辑器进行编码。
Python 元组与列表:共性解析
首先,让我们研究列表和元组之间的相似之处,并通过实例来加深理解。
#1. Python 中的可迭代对象
在Python中,列表用方括号[]
括起来,而元组则用圆括号()
括起来。您也可以直接使用逗号分隔的值来创建元组,而无需括号。
两者都是可迭代的,这意味着您可以使用for
循环来遍历它们。
以下代码展示了如何遍历一个列表:
nums = [2,6,7,10] print(f"nums 的类型是 {type(nums)}") for num in nums: print(num) # 输出 nums 的类型是 <class 'list'> 2 6 7 10
同样,您可以使用循环来遍历元组:
nums = (2,6,7,10) # 注意:nums = 2,6,7,10 也是一个合法的元组。 如果需要,请快速验证! print(f"nums 的类型是 {type(nums)}") for num in nums: print(num) # 输出 nums 的类型是 <class 'tuple'> 2 6 7 10
#2. 从其他序列创建
列表和元组的另一个共同点是它们都可以从现有序列(如字符串)创建。
sample_str = "Coding!"
下面的代码演示了如何使用 list(string)
从字符串创建列表:
list_from_str = list(sample_str) print(list_from_str) # 输出 ['C', 'o', 'd', 'i', 'n', 'g', '!']
类似地,可以使用 tuple(sequence)
从字符串或其他序列创建元组。如下所示:
tuple_from_str = tuple(sample_str) print(tuple_from_str) # 输出 ('C', 'o', 'd', 'i', 'n', 'g', '!')
#3. 支持索引和切片
Python支持零索引,这意味着第一个元素的索引是0,第二个是1,以此类推。此外,Python还支持负索引,其中最后一个元素的索引是-1,倒数第二个元素的索引是-2,以此类推。
list_from_str = ['C', 'o', 'd', 'i', 'n', 'g', '!'] print(list_from_str[1]) # o
索引为 -2 的元素是倒数第二个元素 “g”。
tuple_from_str = ('C', 'o', 'd', 'i', 'n', 'g', '!') print(tuple_from_str[-2]) # g
当您需要处理列表或元组的一部分时,可以使用切片。 list[start:end]
返回从索引 start
开始,到索引 end - 1
结束的列表切片。start
的默认值为 0,end
默认是可迭代对象的最后一个元素。
您可以使用相同的语法对元组进行切片。下面是如何对之前创建的列表和元组进行切片的示例。
list_from_str = ['C', 'o', 'd', 'i', 'n', 'g', '!'] print(list_from_str[0:5]) # 输出 ['C', 'o', 'd', 'i', 'n']
除了起始和结束索引外,还可以指定步长值。 tuple[start:end:step]
返回从 start
到 end-1
的元组切片,步长为 step
。
tuple_from_str = ('C', 'o', 'd', 'i', 'n', 'g', '!') print(tuple_from_str[::2]) # 输出 ('C', 'd', 'n', '!')
这里,我们将步长值设置为 2,因此切片包含每隔一个的元素。
#4. 多种数据类型的集合
在前面的例子中,列表和元组中的所有元素都具有相同的数据类型。
然而,您可以在单个列表或元组中存储不同数据类型的值。
在下面的代码中,student_list
包含了字符串类型的学生姓名、整数类型的年龄和浮点类型的分数。
student_list = ["John",22,96.5] for item in student_list: print(f"{item} 的类型是 {type(item)}") # 输出 John 的类型是 <class 'str'> 22 的类型是 <class 'int'> 96.5 的类型是 <class 'float'>
我们也可以使用类似的例子来演示元组:
student_tuple = ("Jane",23,99.5) for item in student_tuple: print(f"{item} 的类型是 {type(item)}") # 输出 Jane 的类型是 <class 'str'> 23 的类型是 <class 'int'> 99.5 的类型是 <class 'float'>
#5. 支持成员测试
列表和元组都允许您执行成员测试,以检查是否存在特定项目。您可以使用 in
运算符来检查列表或元组中是否存在特定项目。
如果 iterable
包含 item
,则表达式 item in iterable
的计算结果为 True
; 否则,为 False
。
"Alex" in student_list # False "Jane" in student_tuple # True
到目前为止,您已经了解了Python中列表和元组之间的相似之处。接下来,让我们来看看这两种数据结构之间的主要区别。
Python 元组与列表:差异解析
#1. 列表的可变性与元组的不可变性
列表和元组之间最重要的区别在于元组是不可变的。这意味着您不能在原地修改元组。
▶️ 这是一个例子。
tuple1 = ("Java","Python","C++") tuple1[0] = "Rust" # 输出 ----> 2 tuple1[0] = "Rust" TypeError: 'tuple' 对象不支持项赋值
列表是一种可变的数据结构,因此我们可以通过更改特定索引处的项目来修改列表,如下面的代码所示。
list1 = ["Java","Python","C++"] list1[0] = "Rust" print(list1) # 输出 ['Rust', 'Python', 'C++']
#2. 可变长度的列表与固定长度的元组
Python列表是一种可变长度的数据结构。
您可以执行以下操作:
- 向列表末尾添加项目
- 将另一个列表中的项目添加到当前列表的末尾
- 从列表中删除特定索引处的项目
list1 = [2,3,4,5] # 添加一个项目到末尾 list1.append(9) print(list1) # 将 list2 中的项目添加到 list1 的末尾 list2 = [0,7] list1.extend(list2) print(list1) # 从 list1 中删除一个项目 list1.pop(0) print(list1)
▶️ 上述代码片段的输出。
# 输出 [2, 3, 4, 5, 9] [2, 3, 4, 5, 9, 0, 7] [3, 4, 5, 9, 0, 7]
元组是固定长度的数据结构。因此,您不能在现有元组中添加或删除元素。但是,您可以重新定义元组以包含不同的元素。
tuple1 = (2,4,6,8) tuple1 = (1,8,9) print(tuple1) # 输出 (1, 8, 9)
#3. 内存占用
列表是一种可变长度的数据结构。最初定义列表时,会在内存中为其分配特定的大小。当您使用 append()
或 extend()
方法修改列表时,需要分配额外的内存来存储添加的元素。这种分配几乎总是比您添加的元素数量多。
因此,需要跟踪列表中项目的数量和分配的空间。此外,由于列表的长度是可变的,因此有一个指针指向列表项的地址。因此,长度为 k
的列表比具有相同 k
个元素的元组占用更多的内存。
这是一个简单的图示。
您可以使用内置的 sys
模块中的 getsizeof()
方法获取Python对象在内存中的大小。
import sys list1 = [4,5,9,14] list_size = sys.getsizeof(list1) print(f"列表大小:{list_size}") tuple1 = (4,5,9,14) tuple_size = sys.getsizeof(tuple1) print(f"元组大小:{tuple_size}")
对于相同数量和值的元素,列表比元组占用更多内存,如下面的输出所示。
# 输出 列表大小:104 元组大小:88
何时应使用Python元组?
从Python列表和元组的比较中可以看出,如果您需要一个可变的集合,则应使用列表。
那么何时应该使用元组呢?
我们将在本节中讨论。
#1. 只读集合
每当您需要一个不可变的集合时,都应该将其定义为元组。例如, color = (243, 55, 103)
是一个元组,其中包含对应于颜色阴影的RGB值。将颜色定义为元组可以确保其不可修改。
本质上,当您需要一个集合是只读的,即在程序运行时不应该修改其值时,您应该考虑使用元组。这将防止对值的意外修改。
#2. 字典的键
假设您使用列表项 key_list
作为键创建字典。您可以使用 dict.fromkeys()
方法从列表创建字典。
key_list = list("ABCD") dict.fromkeys(key_list) # 输出 {'A': None, 'B': None, 'C': None, 'D': None}
假设您在创建字典之前修改了列表,使”D”成为第一个元素(索引0)。
现在,字典键 “A” 会发生什么?
如果您尝试从 key_list
创建字典并访问与键 “A” 对应的值,则会遇到 KeyError
。
key_list[0] = 'D' dict.fromkeys(key_list)['A'] # 输出 --------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-31-c90392acc2cf> in <module>() ----> 1 dict.fromkeys(key_list)['A'] KeyError: 'A'
字典的键应该是唯一的。因此,您不能有第二个 ‘D’ 作为键。
dict.fromkeys(key_list) # 输出 {'B': None, 'C': None, 'D': None} # A 不再是一个键。
如果您改为使用元组,则不可能进行此类修改,并且您不太可能遇到错误。因此,您应该更喜欢使用元组的项目作为键来创建字典。
key_tuple = tuple("ABCD") dict.fromkeys(key_tuple) # 输出 {'A': None, 'B': None, 'C': None, 'D': None} key_tuple[0] = 'D' --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-12-2cecbefa7db2> in <module>() ----> 1 key_tuple[0] = 'D' TypeError: 'tuple' 对象不支持项赋值
#3. 函数参数
元组的不可变性也使得它们适合作为函数参数传入。
考虑以下函数 find_volume()
,它返回给定尺寸的长方体体积:长度、宽度和高度。
def find_volume(dimensions): l,b,h = dimensions return l*b*h
假设这些维度在一个名为 dimensions
的列表中可用。以维度作为参数调用 find_volume()
将返回体积。
dimensions = [2,8,5] find_volume(dimensions) # 输出 80
您始终可以更改列表中存储的维度。
dimensions = [20,8,5] find_volume(dimensions) # 输出 800
但是,有时您需要这些值保持不变并且不能修改。这时,您应该考虑将参数存储为元组并在函数调用中使用它们。
#4. 函数的返回值
在Python中,您会在函数的返回值中遇到元组。当您从函数返回多个值时,Python会隐式地将它们作为元组返回。
考虑以下函数 return_even()
:
def return_even(num): even = [i for i in range(num) if (i%2==0)] return even,len(even)
- 它需要一个数字
num
作为参数。 - 它返回区间
[0,num)
中的偶数列表以及该列表的长度。
让我们将 num
的值设置为20并调用该函数。
num = 20
调用 return_even()
会以元组的形式返回两个值。您可以使用类型函数来验证返回值类型。
type(return_even(num)) # <class 'tuple'>
您可以打印返回值,以验证它是一个元组,其中第一个元素是偶数列表,第二个元素是该列表的长度。
print(return_even(num)) # 输出 ([0, 2, 4, 6, 8, 10, 12, 14, 16, 18], 10)
由于元组中有两个元素,因此您可以将它们解包为两个变量,如下所示。
even_nums, count = return_even(num) print(even_nums) print(count) # 输出 [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] 10
结论
我希望本教程能够为您提供Python元组与列表的全面比较。
让我们通过一个快速总结来结束本教程:
- 列表和元组是Python中的内置数据结构。
- 相似之处:可迭代,支持索引,切片,不同的数据类型以及成员测试的运算符。
- 关键区别:列表是可变的,而元组是不可变的。
- 其他区别:元组的长度是固定的,而列表的长度是可变的;元组占用较少的内存。
- 何时应该使用元组? 用于不可变的集合、字典的键和函数参数。
接下来,您可以尝试一些Python项目来练习和学习。或者学习从Python列表中删除重复项的方法。祝您学习愉快!编程快乐!👩🏽💻