Python列表和元组的详细区别

Python列表与元组详解
本文深入探讨Python中列表和元组的区别,包括它们的特性、应用场景及内部实现原理。对比了列表的动态性和元组的静态性,并通过实例演示了两者的操作差异。
该文章已生成可运行项目,

Python列表和元组的详细区别

一、列表和元组的区别

  1. 列表是动态数组,它们可变且可以重设长度(改变其内部元素的个数)。
  2. 元组是静态数组,它们不可变,且其内部数据一旦创建便无法改变。
  3. 元组缓存于Python运行时环境,这意味着我们每次使用元组时无须访问内核去分配内存。

这些区别结实率两者在设计哲学上的不同:

  • 列表可被用于保存多个互相独立对象的数据集合
  • 元组用于描述一个不会改变的事务的多个属性

二、列表(List)

列表一旦创建了我们就可以根据自己的需要随意改变它的内容:

>>> l = [1, 2, 3, 4, 5, 6]
>>> l[0] = l[2] * l[3]
>>> l
[12, 2, 3, 4, 5, 6]

另外我们可以给列边添加新的数据来增加其大小:

>>> len(l)
6
>>> l.append(7)
>>> l
[12, 2, 3, 4, 5, 6, 7]
>>> len(l)
7

这是因为动态数组支持resize操作,可以增加数组的容量。当一个大小为N的列表第一次需要添加数据时,Python会创建一个新的列表,足够放原来的N个元素以及额外添加的元素。不过,实际分配的并不是N+1个元素,而是M个元素,M > N, 这是为了给未来的添加预留空间。然后旧列表的数据被复制到新列表中,旧列表则会被销毁。从设计理念上来说,第一次添加可能是后续多次添加的开始,通过预留空间的做法,我们就可以减少这一分配空间的操作次数以及内存复制的次数。这点非常重要,因为内存复制可能非常的昂贵,特别是当列表大小开始增长以后。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GdQpXs7R-1599024560319)(./image/列表的添加操作.jpg)]

三、元组(Tuple)

元组是固定且不可改变的。这意味着一旦元组被创建,和列表不同,它的内容无法被修改或它的大小也无法被改变。

>>> t = (1, 2, 3, 4)
>>> t[0] = 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

虽然它们不支持改变大小,但是我们可以将两个元组合并成一个新元组。这一操作类似列表的resize操作,但我们不需要为新生的元组分配任何额外的空间:

>>> t1 = (1, 2, 3, 4)
>>> t2 = (5, 6, 7, 8)
>>> t1 + t2
(1, 2, 3, 4, 5, 6, 7, 8)

如果我们将其与列表的append操作比较,我们会看到它的复杂度是O(n)而不是列表的O(1)。这是因为对元组每添加一个新元素都会有分配和复制操作,而不是像列表那样仅在额外的空间耗尽时发生。所以元组并没有提供一个类似append的自增操作,任意两个元组相加始终返回一个新分配的元组。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nIsaGxH8-1599024560321)(./image/元组的合并操作.jpg)]

该网站为Python Tutor,一个能够对python运行内存可视化的网站,非常适合初学者研究,在运行过程中内存发生了什么。

元组的静态特性的另一个好处体现在一些会在Python后台发生的事情:资源缓存。

Python是一门垃圾收集语言,这意味着当一个变量不再被使用时,Python会将该变量使用的内存释放回操作系统,以供其他程序(变量)使用。然而,对于长度为1~20的元组,即使它们不在被使用,它们的空间也不会立刻还给系统,而是留待未来使用。这意味着当未来需要一个同样大小的新的元组时,我们不再需要向操作系统申请一块内存来存放数据,因为我们已经有了预留的空间。

这看上去可能是个细微的好处,但是实际上是元组一个很神奇的地方:它们可以被轻松快速地创建,因为它们可以避免跟操作系统频繁的打交道,而后者会花很长的时间。

下面举个例子会非常直观的说明问题

In [1]: %timeit l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
93.7 ns ± 3.33 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [2]: %timeit t = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
18.5 ns ± 1.19 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

上面的示例中显示了初始化一个列表比初始化一个元组慢了5.1倍——如果这是在一个循环中,这点差别会很快的累加起来。

本文章已经生成可运行项目
### Python 元组(tuple)的基本概念用法 Python 中的元组(tuple)是一种不可变的序列类型,与列表(list)类似,但其元素在创建后不能修改。元组使用小括号 `()` 来定义,元素之间用逗号分隔。由于其不可变性,元组通常用于存储不需要修改的数据,这有助于提高程序的安全性性能。 #### 创建元组 元组可以通过多种方式创建: - 直接定义:使用小括号并用逗号分隔元素。例如: ```python tup1 = ('physics', 'chemistry', 1997, 2000) tup2 = (1, 2, 3, 4, 5) tup3 = "a", "b", "c", "d" # 不带括号也可以 ``` - 将其他可迭代对象(如列表)转换为元组:可以使用内置的 `tuple()` 函数[^1]。 ```python li = [1, 2, 3, 4] a = tuple(li) # 将列表转换为元组 ``` - 创建空元组: ```python tup_empty = () ``` - 创建包含单个元素的元组:必须在元素后加逗号,否则会被视为普通变量。 ```python tup_single = (50,) ``` #### 元组的不可变性 元组一旦创建,就不能进行修改,这意味着不能添加、删除或更改元组中的元素。因此,元组没有像列表那样的 `append()` 或 `insert()` 方法。然而,如果元组中包含可变对象(如列表),则可以通过索引访问该对象并对其进行修改[^2]。 ```python t = ('a', 'b', ['A', 'B']) t[2][0] = 'X' t[2][1] = 'Y' # 输出: ('a', 'b', ['X', 'Y']) print(t) ``` #### 元组的操作 尽管元组是不可变的,但仍然可以执行一些基本操作: - **连接**:两个元组可以通过 `+` 运算符连接成一个新的元组。 ```python tuple1 = (1, 2, 3, 4, 5) tuple2 = (6, 7, 8, 9, 10) tuple3 = tuple1 + tuple2 # 输出: (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) ``` - **长度计算**:使用 `len()` 函数可以获取元组的长度。 ```python length = len(tuple1) # 输出: 5 ``` - **成员检查**:使用 `in` 关键字可以检查某个元素是否存在于元组中。 ```python 'a' in t # 返回 True 或 False ``` - **比较**:可以使用 `cmp()` 函数比较两个元组的大小(注意:在 Python 3 中已移除此函数)。 ```python # cmp(tuple1, tuple2) # Python 2 中可用 ``` - **最大值/最小值**:使用 `max()` `min()` 函数可以分别获取元组中的最大值最小值。 ```python max_value = max(tuple2) # 输出: 10 min_value = min(tuple2) # 输出: 6 ``` #### 使用场景 元组适用于以下几种情况: - 当数据不应被修改时,例如配置信息或常量集合。 - 作为字典的键(因为元组是不可变的,而列表不可哈希,不能作为字典的键)。 - 作为函数返回值,特别是当需要返回多个值时,Python 实际上返回的是一个元组。 ###
评论 14
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值